Merge branches 'pm-cpuidle', 'pm-sleep' and 'pm-powercap'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 13 May 2024 18:14:10 +0000 (20:14 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 13 May 2024 18:14:10 +0000 (20:14 +0200)
Merge cpuidle updates, changes related to system sleep and power capping
updates for 6.10:

 - Fix kerneldoc description of ladder_do_selection() (Jeff Johnson).

 - Convert the cpuidle kirkwood driver to platform remove callback
   returning void (Yangtao Li).

 - Replace deprecated strncpy() with strscpy() in the hibernation core
   code (Justin Stitt).

 - Use %ps to simplify debug output in the core system-wide suspend and
   resume code (Len Brown).

 - Remove unnecessary else from device_init_wakeup() and make
   device_wakeup_disable() return void (Dhruva Gole).

 - Enable PMU support in the Intel TPMI RAPL driver (Zhang Rui).

 - Add support for ArrowLake-H platform to the Intel RAPL driver (Zhang
   Rui).

 - Avoid explicit cpumask allocation on stack in DTPM (Dawei Li).

* pm-cpuidle:
  cpuidle: ladder: fix ladder_do_selection() kernel-doc
  cpuidle: kirkwood: Convert to platform remove callback returning void

* pm-sleep:
  PM: hibernate: replace deprecated strncpy() with strscpy()
  PM: sleep: Take advantage of %ps to simplify debug output
  PM: wakeup: Remove unnecessary else from device_init_wakeup()
  PM: wakeup: make device_wakeup_disable() return void

* pm-powercap:
  powercap: intel_rapl_tpmi: Enable PMU support
  powercap: intel_rapl: Introduce APIs for PMU support
  powercap: intel_rapl: Sort header files
  powercap: intel_rapl: Add support for ArrowLake-H platform
  powercap: DTPM: Avoid explicit cpumask allocation on stack

906 files changed:
.mailmap
Documentation/admin-guide/kernel-parameters.txt
Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst
Documentation/core-api/workqueue.rst
Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
Documentation/devicetree/bindings/eeprom/at24.yaml
Documentation/devicetree/bindings/iio/health/maxim,max30102.yaml
Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml
Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml
Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml
Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml
Documentation/devicetree/bindings/soc/rockchip/grf.yaml
Documentation/devicetree/bindings/sound/rt5645.txt
Documentation/mm/page_owner.rst
Documentation/process/embargoed-hardware-issues.rst
Documentation/rust/arch-support.rst
Documentation/timers/no_hz.rst
Documentation/translations/zh_CN/core-api/workqueue.rst
MAINTAINERS
Makefile
arch/Kconfig
arch/arc/Kconfig
arch/arc/boot/Makefile
arch/arc/boot/dts/axc003.dtsi
arch/arc/boot/dts/hsdk.dts
arch/arc/boot/dts/vdk_axs10x_mb.dtsi
arch/arc/include/asm/cachetype.h [deleted file]
arch/arc/include/asm/dsp.h
arch/arc/include/asm/entry-compact.h
arch/arc/include/asm/entry.h
arch/arc/include/asm/irq.h
arch/arc/include/asm/irqflags-compact.h
arch/arc/include/asm/mmu_context.h
arch/arc/include/asm/pgtable-bits-arcv2.h
arch/arc/include/asm/ptrace.h
arch/arc/include/asm/shmparam.h
arch/arc/include/asm/smp.h
arch/arc/include/asm/thread_info.h
arch/arc/include/uapi/asm/swab.h
arch/arc/kernel/entry-arcv2.S
arch/arc/kernel/entry.S
arch/arc/kernel/head.S
arch/arc/kernel/intc-arcv2.c
arch/arc/kernel/kprobes.c
arch/arc/kernel/perf_event.c
arch/arc/kernel/setup.c
arch/arc/kernel/signal.c
arch/arc/kernel/traps.c
arch/arc/kernel/vmlinux.lds.S
arch/arc/mm/tlb.c
arch/arc/mm/tlbex.S
arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts
arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-common.dtsi
arch/arm/net/bpf_jit_32.c
arch/arm64/boot/dts/allwinner/sun50i-h616-bigtreetech-cb1.dtsi
arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts
arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
arch/arm64/boot/dts/allwinner/sun50i-h618-longan-module-3h.dtsi
arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero2w.dts
arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero3.dts
arch/arm64/boot/dts/allwinner/sun50i-h618-transpeed-8k618-t.dts
arch/arm64/boot/dts/freescale/imx8mp.dtsi
arch/arm64/boot/dts/mediatek/mt2712-evb.dts
arch/arm64/boot/dts/mediatek/mt2712e.dtsi
arch/arm64/boot/dts/mediatek/mt7622.dtsi
arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
arch/arm64/boot/dts/mediatek/mt7986a.dtsi
arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
arch/arm64/boot/dts/mediatek/mt8183.dtsi
arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi
arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
arch/arm64/boot/dts/mediatek/mt8192.dtsi
arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
arch/arm64/boot/dts/mediatek/mt8195.dtsi
arch/arm64/boot/dts/qcom/sc7280.dtsi
arch/arm64/boot/dts/qcom/sc8180x.dtsi
arch/arm64/boot/dts/qcom/sc8280xp.dtsi
arch/arm64/boot/dts/qcom/sm6350.dtsi
arch/arm64/boot/dts/qcom/sm6375.dtsi
arch/arm64/boot/dts/qcom/sm8250.dtsi
arch/arm64/boot/dts/qcom/sm8450.dtsi
arch/arm64/boot/dts/qcom/sm8550.dtsi
arch/arm64/boot/dts/qcom/sm8650.dtsi
arch/arm64/boot/dts/qcom/x1e80100.dtsi
arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi
arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts
arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts
arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi
arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
arch/arm64/kernel/head.S
arch/arm64/kvm/vgic/vgic-kvm-device.c
arch/arm64/mm/hugetlbpage.c
arch/arm64/mm/pageattr.c
arch/arm64/net/bpf_jit_comp.c
arch/loongarch/Kconfig
arch/loongarch/include/asm/crash_core.h [deleted file]
arch/loongarch/include/asm/crash_reserve.h [new file with mode: 0644]
arch/loongarch/include/asm/perf_event.h
arch/loongarch/include/asm/tlb.h
arch/loongarch/kernel/perf_event.c
arch/loongarch/mm/fault.c
arch/powerpc/crypto/chacha-p10-glue.c
arch/powerpc/include/asm/plpks.h
arch/powerpc/kernel/iommu.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/plpks.c
arch/riscv/Kconfig.errata
arch/riscv/errata/thead/errata.c
arch/riscv/include/asm/errata_list.h
arch/riscv/include/asm/page.h
arch/riscv/include/asm/pgtable.h
arch/riscv/include/uapi/asm/hwprobe.h
arch/riscv/mm/init.c
arch/riscv/net/bpf_jit_comp64.c
arch/s390/crypto/paes_s390.c
arch/s390/include/asm/dwarf.h
arch/s390/kernel/entry.S
arch/s390/kernel/vdso64/vdso_user_wrapper.S
arch/s390/mm/gmap.c
arch/s390/mm/hugetlbpage.c
arch/x86/Kconfig
arch/x86/entry/common.c
arch/x86/entry/entry_fred.c
arch/x86/entry/vsyscall/vsyscall_64.c
arch/x86/events/intel/lbr.c
arch/x86/include/asm/barrier.h
arch/x86/include/asm/coco.h
arch/x86/include/asm/e820/api.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/perf_event.h
arch/x86/include/asm/pgtable_types.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/sev.h
arch/x86/kernel/apic/apic.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/cpuid-deps.c
arch/x86/kernel/e820.c
arch/x86/kernel/process_64.c
arch/x86/kernel/sev-shared.c
arch/x86/kvm/Makefile
arch/x86/kvm/cpuid.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/mmu/tdp_mmu.c
arch/x86/kvm/pmu.c
arch/x86/kvm/svm/sev.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/svm/svm.h
arch/x86/kvm/svm/vmenter.S
arch/x86/kvm/vmx/pmu_intel.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h
arch/x86/kvm/x86.c
arch/x86/lib/retpoline.S
arch/x86/mm/fault.c
arch/x86/mm/mem_encrypt.c
arch/x86/net/bpf_jit_comp.c
arch/x86/virt/svm/sev.c
arch/x86/xen/enlighten_pv.c
arch/x86/xen/smp_pv.c
arch/xtensa/include/asm/cacheflush.h
arch/xtensa/include/asm/processor.h
arch/xtensa/include/asm/ptrace.h
arch/xtensa/kernel/process.c
arch/xtensa/kernel/stacktrace.c
arch/xtensa/platforms/iss/console.c
block/bdev.c
block/blk-iocost.c
block/ioctl.c
drivers/accessibility/speakup/main.c
drivers/acpi/cppc_acpi.c
drivers/acpi/x86/s2idle.c
drivers/android/binder.c
drivers/base/power/main.c
drivers/base/power/wakeup.c
drivers/base/regmap/regmap.c
drivers/block/ublk_drv.c
drivers/bluetooth/btmtk.c
drivers/bluetooth/btqca.c
drivers/bluetooth/btusb.c
drivers/bluetooth/hci_qca.c
drivers/char/random.c
drivers/clk/clk.c
drivers/clk/mediatek/clk-mt7988-infracfg.c
drivers/clk/mediatek/clk-mtk.c
drivers/clk/qcom/clk-smd-rpm.c
drivers/clk/qcom/gdsc.c
drivers/clk/samsung/clk-exynos-clkout.c
drivers/clk/sunxi-ng/ccu-sun50i-a64.c
drivers/clk/sunxi-ng/ccu-sun50i-h6.c
drivers/clk/sunxi-ng/ccu_common.c
drivers/clk/sunxi-ng/ccu_common.h
drivers/comedi/drivers/vmk80xx.c
drivers/cpufreq/amd-pstate.c
drivers/cpufreq/brcmstb-avs-cpufreq.c
drivers/cpufreq/cppc_cpufreq.c
drivers/cpufreq/cpufreq-dt-platdev.c
drivers/cpufreq/cpufreq-dt.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/freq_table.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/mediatek-cpufreq.c
drivers/cpufreq/sun50i-cpufreq-nvmem.c
drivers/cpufreq/tegra124-cpufreq.c
drivers/cpufreq/ti-cpufreq.c
drivers/cpuidle/cpuidle-kirkwood.c
drivers/cpuidle/governors/ladder.c
drivers/cxl/core/mbox.c
drivers/cxl/core/port.c
drivers/devfreq/event/exynos-nocp.c
drivers/devfreq/event/exynos-ppmu.c
drivers/devfreq/exynos-bus.c
drivers/devfreq/mtk-cci-devfreq.c
drivers/devfreq/rk3399_dmc.c
drivers/devfreq/sun8i-a33-mbus.c
drivers/dma/idma64.c
drivers/dma/idxd/cdev.c
drivers/dma/idxd/debugfs.c
drivers/dma/idxd/device.c
drivers/dma/idxd/idxd.h
drivers/dma/idxd/init.c
drivers/dma/idxd/irq.c
drivers/dma/idxd/perfmon.c
drivers/dma/owl-dma.c
drivers/dma/pl330.c
drivers/dma/tegra186-gpc-dma.c
drivers/dma/xilinx/xdma-regs.h
drivers/dma/xilinx/xdma.c
drivers/dma/xilinx/xilinx_dpdma.c
drivers/dpll/dpll_core.c
drivers/edac/versal_edac.c
drivers/firewire/nosy.c
drivers/firewire/ohci.c
drivers/firmware/efi/unaccepted_memory.c
drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
drivers/firmware/qcom/qcom_scm.c
drivers/firmware/smccc/smccc.c
drivers/fpga/dfl-pci.c
drivers/gpio/gpio-crystalcove.c
drivers/gpio/gpio-lpc32xx.c
drivers/gpio/gpio-tangier.c
drivers/gpio/gpio-tegra186.c
drivers/gpio/gpio-wcove.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
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/sdma_v4_4_2.c
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
drivers/gpu/drm/amd/amdkfd/kfd_process.c
drivers/gpu/drm/amd/amdkfd/kfd_svm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c
drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c
drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c
drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/pm/amdgpu_pm.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
drivers/gpu/drm/drm_gem_atomic_helper.c
drivers/gpu/drm/etnaviv/etnaviv_gpu.c
drivers/gpu/drm/etnaviv/etnaviv_gpu.h
drivers/gpu/drm/etnaviv/etnaviv_hwdb.c
drivers/gpu/drm/gma500/Makefile
drivers/gpu/drm/gma500/psb_device.c
drivers/gpu/drm/gma500/psb_drv.h
drivers/gpu/drm/gma500/psb_lid.c [deleted file]
drivers/gpu/drm/imagination/pvr_fw_mips.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_dp.c
drivers/gpu/drm/nouveau/nvkm/core/firmware.c
drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
drivers/gpu/drm/panel/Kconfig
drivers/gpu/drm/panel/panel-ilitek-ili9341.c
drivers/gpu/drm/panel/panel-novatek-nt36672e.c
drivers/gpu/drm/panel/panel-visionox-rm69299.c
drivers/gpu/drm/radeon/pptable.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/ttm/ttm_pool.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/v3d/v3d_irq.c
drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_bo.h
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
drivers/gpu/drm/vmwgfx/vmwgfx_gem.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
drivers/gpu/drm/xe/display/intel_fb_bo.c
drivers/gpu/drm/xe/xe_gt.c
drivers/gpu/drm/xe/xe_gt_ccs_mode.c
drivers/gpu/drm/xe/xe_gt_ccs_mode.h
drivers/gpu/drm/xe/xe_guc_ct.c
drivers/gpu/drm/xe/xe_huc.c
drivers/gpu/drm/xe/xe_vm.c
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-mcp2221.c
drivers/hid/hid-nintendo.c
drivers/hid/i2c-hid/i2c-hid-core.c
drivers/hid/intel-ish-hid/ipc/ipc.c
drivers/i2c/i2c-core-base.c
drivers/iio/accel/mxc4005.c
drivers/iio/imu/adis16475.c
drivers/iio/pressure/bmp280-core.c
drivers/iio/pressure/bmp280-spi.c
drivers/iio/pressure/bmp280.h
drivers/infiniband/core/cm.c
drivers/infiniband/hw/mlx5/mad.c
drivers/infiniband/sw/rxe/rxe.c
drivers/input/joystick/xpad.c
drivers/input/mouse/amimouse.c
drivers/interconnect/core.c
drivers/interconnect/qcom/x1e80100.c
drivers/iommu/iommufd/Kconfig
drivers/irqchip/irq-gic-v3-its.c
drivers/md/dm-vdo/murmurhash3.c
drivers/md/dm.c
drivers/misc/cardreader/rtsx_pcr.c
drivers/misc/eeprom/at24.c
drivers/misc/mei/hw-me-regs.h
drivers/misc/mei/pci-me.c
drivers/misc/mei/platform-vsc.c
drivers/misc/mei/pxp/mei_pxp.c
drivers/misc/mei/vsc-tp.c
drivers/misc/mei/vsc-tp.h
drivers/misc/pvpanic/pvpanic-pci.c
drivers/mmc/host/moxart-mmc.c
drivers/mmc/host/sdhci-msm.c
drivers/mmc/host/sdhci-of-dwcmshc.c
drivers/mmc/host/sdhci-pci-core.c
drivers/mtd/mtdcore.c
drivers/mtd/nand/raw/brcmnand/brcmnand.c
drivers/mtd/nand/raw/diskonchip.c
drivers/mtd/nand/raw/qcom_nandc.c
drivers/net/dsa/mt7530.c
drivers/net/dsa/mt7530.h
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/port.h
drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/broadcom/genet/bcmgenet.h
drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
drivers/net/ethernet/broadcom/genet/bcmmii.c
drivers/net/ethernet/brocade/bna/bnad_debugfs.c
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/intel/e1000e/phy.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/ice/ice_debugfs.c
drivers/net/ethernet/intel/ice/ice_tc_lib.c
drivers/net/ethernet/intel/ice/ice_vf_lib.c
drivers/net/ethernet/intel/igc/igc.h
drivers/net/ethernet/intel/igc/igc_leds.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
drivers/net/ethernet/mediatek/mtk_wed.c
drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/mellanox/mlxsw/core_env.c
drivers/net/ethernet/mellanox/mlxsw/pci.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
drivers/net/ethernet/qlogic/qede/qede_filter.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/ti/am65-cpsw-nuss.c
drivers/net/ethernet/ti/am65-cpts.c
drivers/net/ethernet/ti/icssg/icssg_prueth.c
drivers/net/ethernet/wangxun/libwx/wx_lib.c
drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
drivers/net/gtp.c
drivers/net/macsec.c
drivers/net/phy/dp83869.c
drivers/net/phy/mediatek-ge-soc.c
drivers/net/tun.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/qmi_wwan.c
drivers/net/vxlan/vxlan_core.c
drivers/net/wireless/ath/ath11k/mac.c
drivers/net/wireless/intel/iwlwifi/cfg/bz.c
drivers/net/wireless/intel/iwlwifi/cfg/sc.c
drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
drivers/net/wireless/intel/iwlwifi/mvm/link.c
drivers/net/wireless/intel/iwlwifi/mvm/scan.c
drivers/net/wireless/virtual/mac80211_hwsim.c
drivers/nfc/trf7970a.c
drivers/nvme/host/core.c
drivers/nvme/host/multipath.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/tcp.c
drivers/nvme/target/auth.c
drivers/nvme/target/configfs.c
drivers/nvme/target/core.c
drivers/nvme/target/nvmet.h
drivers/nvme/target/tcp.c
drivers/phy/freescale/phy-fsl-imx8m-pcie.c
drivers/phy/marvell/phy-mvebu-a3700-comphy.c
drivers/phy/qualcomm/phy-qcom-m31.c
drivers/phy/qualcomm/phy-qcom-qmp-combo.c
drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v5.h
drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v6.h
drivers/phy/rockchip/Kconfig
drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
drivers/phy/ti/phy-tusb1210.c
drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
drivers/pinctrl/core.c
drivers/pinctrl/devicetree.c
drivers/pinctrl/intel/pinctrl-baytrail.c
drivers/pinctrl/intel/pinctrl-intel.h
drivers/pinctrl/mediatek/pinctrl-paris.c
drivers/pinctrl/meson/pinctrl-meson-a1.c
drivers/pinctrl/renesas/pinctrl-rzg2l.c
drivers/platform/x86/amd/pmc/pmc-quirks.c
drivers/platform/x86/amd/pmf/Makefile
drivers/platform/x86/amd/pmf/acpi.c
drivers/platform/x86/amd/pmf/core.c
drivers/platform/x86/amd/pmf/pmf-quirks.c [new file with mode: 0644]
drivers/platform/x86/amd/pmf/pmf.h
drivers/platform/x86/intel/speed_select_if/isst_if_common.c
drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
drivers/power/supply/mt6360_charger.c
drivers/power/supply/rt9455_charger.c
drivers/pwm/pwm-dwc-core.c
drivers/pwm/pwm-dwc.c
drivers/pwm/pwm-dwc.h
drivers/regulator/irq_helpers.c
drivers/regulator/mt6360-regulator.c
drivers/regulator/qcom-refgen-regulator.c
drivers/regulator/vqmmc-ipq4019-regulator.c
drivers/s390/char/raw3270.c
drivers/s390/cio/cio_inject.c
drivers/s390/cio/device.c
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_ops.c
drivers/s390/cio/qdio_main.c
drivers/s390/crypto/zcrypt_ccamisc.c
drivers/s390/crypto/zcrypt_ep11misc.c
drivers/s390/net/ism_drv.c
drivers/s390/net/qeth_core_main.c
drivers/scsi/scsi_lib.c
drivers/scsi/sd.c
drivers/slimbus/qcom-ngd-ctrl.c
drivers/soc/mediatek/Kconfig
drivers/soc/mediatek/mtk-svs.c
drivers/soundwire/amd_manager.c
drivers/soundwire/amd_manager.h
drivers/spi/spi-axi-spi-engine.c
drivers/spi/spi-hisi-kunpeng.c
drivers/spi/spi.c
drivers/thermal/thermal_debugfs.c
drivers/thunderbolt/switch.c
drivers/thunderbolt/tb.c
drivers/thunderbolt/tb.h
drivers/thunderbolt/usb4.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/8250/8250_lpc18xx.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/mxs-auart.c
drivers/tty/serial/pmac_zilog.c
drivers/tty/serial/serial_base.h
drivers/tty/serial/serial_core.c
drivers/tty/serial/serial_port.c
drivers/tty/serial/stm32-usart.c
drivers/ufs/host/ufs-qcom.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/hub.c
drivers/usb/core/port.c
drivers/usb/dwc2/hcd_ddma.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/dwc3/host.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/f_ncm.c
drivers/usb/gadget/function/uvc_configfs.c
drivers/usb/gadget/udc/fsl_udc_core.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/xhci-plat.h
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci-rzv2m.c
drivers/usb/host/xhci-trace.h
drivers/usb/misc/onboard_usb_hub.c
drivers/usb/serial/option.c
drivers/usb/typec/mux/it5205.c
drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/typec/ucsi/ucsi.c
drivers/vdpa/vdpa.c
drivers/video/fbdev/core/fb_defio.c
drivers/virt/vmgenid.c
fs/9p/fid.h
fs/9p/v9fs.h
fs/9p/vfs_file.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/9p/vfs_super.c
fs/bcachefs/backpointers.c
fs/bcachefs/backpointers.h
fs/bcachefs/bcachefs.h
fs/bcachefs/bcachefs_format.h
fs/bcachefs/bkey.h
fs/bcachefs/bkey_methods.c
fs/bcachefs/btree_cache.c
fs/bcachefs/btree_gc.c
fs/bcachefs/btree_io.c
fs/bcachefs/btree_iter.h
fs/bcachefs/btree_key_cache.c
fs/bcachefs/btree_node_scan.c
fs/bcachefs/btree_node_scan_types.h
fs/bcachefs/btree_trans_commit.c
fs/bcachefs/btree_types.h
fs/bcachefs/btree_update_interior.c
fs/bcachefs/btree_write_buffer.c
fs/bcachefs/buckets.c
fs/bcachefs/buckets.h
fs/bcachefs/chardev.c
fs/bcachefs/checksum.c
fs/bcachefs/checksum.h
fs/bcachefs/compress.h
fs/bcachefs/ec.c
fs/bcachefs/ec.h
fs/bcachefs/extents.c
fs/bcachefs/fs-io-direct.c
fs/bcachefs/fs-io.c
fs/bcachefs/fs.c
fs/bcachefs/inode.c
fs/bcachefs/journal_io.c
fs/bcachefs/opts.c
fs/bcachefs/opts.h
fs/bcachefs/recovery.c
fs/bcachefs/recovery_passes.c
fs/bcachefs/sb-clean.c
fs/bcachefs/sb-downgrade.c
fs/bcachefs/sb-errors_types.h
fs/bcachefs/sb-members.c
fs/bcachefs/sb-members.h
fs/bcachefs/super-io.c
fs/bcachefs/super.c
fs/bcachefs/super_types.h
fs/bcachefs/sysfs.c
fs/bcachefs/thread_with_file.c
fs/bcachefs/thread_with_file.h
fs/btrfs/backref.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_map.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/messages.c
fs/btrfs/ordered-data.c
fs/btrfs/qgroup.c
fs/btrfs/scrub.c
fs/btrfs/tests/extent-map-tests.c
fs/btrfs/volumes.c
fs/erofs/fscache.c
fs/erofs/internal.h
fs/erofs/super.c
fs/eventpoll.c
fs/fuse/cuse.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/fuse/iomode.c
fs/ioctl.c
fs/netfs/buffered_write.c
fs/nfs/inode.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4xdr.c
fs/nfsd/state.h
fs/nilfs2/dir.c
fs/ntfs3/Kconfig
fs/ntfs3/dir.c
fs/ntfs3/file.c
fs/ntfs3/inode.c
fs/ntfs3/ntfs_fs.h
fs/ntfs3/super.c
fs/proc/page.c
fs/smb/client/cifsfs.c
fs/smb/client/cifsglob.h
fs/smb/client/cifspdu.h
fs/smb/client/cifsproto.h
fs/smb/client/connect.c
fs/smb/client/fs_context.c
fs/smb/client/fs_context.h
fs/smb/client/fscache.c
fs/smb/client/misc.c
fs/smb/client/smb2misc.c
fs/smb/client/smb2ops.c
fs/smb/client/smb2pdu.c
fs/smb/client/smb2pdu.h
fs/smb/client/smb2transport.c
fs/smb/client/trace.h
fs/smb/client/transport.c
fs/smb/common/smb2pdu.h
fs/smb/server/ksmbd_netlink.h
fs/smb/server/server.c
fs/smb/server/smb2pdu.c
fs/smb/server/vfs.c
fs/squashfs/inode.c
fs/sysfs/file.c
fs/tracefs/event_inode.c
fs/tracefs/inode.c
fs/tracefs/internal.h
include/asm-generic/barrier.h
include/linux/amd-pstate.h
include/linux/blkdev.h
include/linux/bootconfig.h
include/linux/clk.h
include/linux/cpu.h
include/linux/etherdevice.h
include/linux/filter.h
include/linux/firmware/qcom/qcom_qseecom.h
include/linux/firmware/qcom/qcom_scm.h
include/linux/gpio/property.h
include/linux/mm.h
include/linux/page-flags.h
include/linux/peci.h
include/linux/pm_wakeup.h
include/linux/profile.h
include/linux/regmap.h
include/linux/regulator/consumer.h
include/linux/shmem_fs.h
include/linux/skmsg.h
include/linux/sunrpc/svc_rdma.h
include/linux/swapops.h
include/linux/tracefs.h
include/linux/udp.h
include/net/af_unix.h
include/net/bluetooth/hci_core.h
include/net/gro.h
include/net/mac80211.h
include/net/macsec.h
include/net/netfilter/nf_flow_table.h
include/net/netfilter/nf_tables.h
include/net/sch_generic.h
include/net/sock.h
include/net/tls.h
include/sound/cs35l56.h
include/sound/emu10k1.h
include/trace/events/mmflags.h
include/trace/events/rpcgss.h
include/uapi/drm/etnaviv_drm.h
include/uapi/linux/vdpa.h
init/Kconfig
init/main.c
kernel/bounds.c
kernel/bpf/core.c
kernel/bpf/verifier.c
kernel/configs/hardening.config
kernel/cpu.c
kernel/dma/swiotlb.c
kernel/fork.c
kernel/power/hibernate.c
kernel/profile.c
kernel/sched/fair.c
kernel/sched/isolation.c
kernel/sched/sched.h
kernel/softirq.c
kernel/trace/trace_events.c
kernel/trace/trace_probe.c
kernel/vmcore_info.c
kernel/workqueue.c
lib/Kconfig.debug
lib/bootconfig.c
lib/dynamic_debug.c
lib/scatterlist.c
lib/stackdepot.c
lib/ubsan.c
mm/gup.c
mm/huge_memory.c
mm/hugetlb.c
mm/internal.h
mm/madvise.c
mm/memory-failure.c
mm/page_owner.c
mm/shmem.c
mm/zswap.c
net/8021q/vlan_core.c
net/ax25/af_ax25.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sync.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/mgmt.c
net/bluetooth/sco.c
net/bridge/br_forward.c
net/bridge/br_input.c
net/bridge/br_netfilter_hooks.c
net/bridge/br_netlink.c
net/bridge/br_private.h
net/bridge/netfilter/nf_conntrack_bridge.c
net/core/dev.c
net/core/filter.c
net/core/gro.c
net/core/skbuff.c
net/core/skmsg.c
net/ethernet/eth.c
net/ipv4/af_inet.c
net/ipv4/fib_frontend.c
net/ipv4/icmp.c
net/ipv4/ip_output.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/tcp_ao.c
net/ipv4/udp.c
net/ipv4/udp_offload.c
net/ipv6/ip6_offload.c
net/ipv6/udp.c
net/ipv6/udp_offload.c
net/l2tp/l2tp_eth.c
net/mac80211/chan.c
net/mac80211/mesh.c
net/mac80211/mesh.h
net/mac80211/mesh_pathtbl.c
net/mac80211/mlme.c
net/mac80211/rate.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/tx.c
net/mptcp/protocol.c
net/netfilter/ipvs/ip_vs_proto_sctp.c
net/netfilter/nf_flow_table_inet.c
net/netfilter/nf_flow_table_ip.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_chain_filter.c
net/netfilter/nft_lookup.c
net/netfilter/nft_set_bitmap.c
net/netfilter/nft_set_hash.c
net/netfilter/nft_set_pipapo.c
net/netfilter/nft_set_rbtree.c
net/nsh/nsh.c
net/openvswitch/conntrack.c
net/rxrpc/conn_object.c
net/rxrpc/insecure.c
net/rxrpc/rxkad.c
net/rxrpc/txbuf.c
net/sched/sch_generic.c
net/sunrpc/xprtrdma/svc_rdma_rw.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c
net/sunrpc/xprtsock.c
net/tipc/msg.c
net/tls/tls.h
net/tls/tls_strp.c
net/unix/af_unix.c
net/unix/garbage.c
net/wireless/nl80211.c
net/wireless/trace.h
rust/Makefile
rust/kernel/init.rs
rust/kernel/lib.rs
rust/kernel/net/phy.rs
rust/macros/lib.rs
rust/macros/module.rs
scripts/Makefile.build
sound/core/seq/seq_ump_convert.c
sound/hda/intel-dsp-config.c
sound/hda/intel-sdw-acpi.c
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/emuproc.c
sound/pci/emu10k1/io.c
sound/pci/hda/cs35l56_hda.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/tas2781_hda_i2c.c
sound/soc/amd/yc/acp6x-mach.c
sound/soc/codecs/cs35l41.c
sound/soc/codecs/cs35l56-sdw.c
sound/soc/codecs/cs35l56-shared.c
sound/soc/codecs/cs35l56.c
sound/soc/codecs/da7219-aad.c
sound/soc/codecs/rt5645.c
sound/soc/codecs/rt715-sdca.c
sound/soc/codecs/rt715-sdw.c
sound/soc/codecs/rt722-sdca.c
sound/soc/codecs/rt722-sdca.h
sound/soc/codecs/wsa881x.c
sound/soc/intel/avs/icl.c
sound/soc/intel/avs/topology.c
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/meson/Kconfig
sound/soc/meson/axg-card.c
sound/soc/meson/axg-fifo.c
sound/soc/meson/axg-tdm-formatter.c
sound/soc/meson/axg-tdm-interface.c
sound/soc/meson/axg-tdm.h
sound/soc/sof/core.c
sound/soc/sof/debug.c
sound/soc/sof/intel/pci-lnl.c
sound/soc/sof/ipc3-pcm.c
sound/soc/sof/ipc4-pcm.c
sound/soc/sof/pcm.c
sound/soc/sof/sof-audio.h
sound/soc/tegra/tegra186_dspk.c
sound/soc/ti/davinci-mcasp.c
tools/arch/arm64/include/asm/cputype.h
tools/arch/arm64/include/uapi/asm/kvm.h
tools/arch/powerpc/include/uapi/asm/kvm.h
tools/arch/s390/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/irq_vectors.h
tools/arch/x86/include/asm/msr-index.h
tools/arch/x86/include/asm/required-features.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/include/asm-generic/bitops/__fls.h
tools/include/asm-generic/bitops/fls.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/fs.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/sound/asound.h
tools/net/ynl/lib/ynl.py
tools/perf/arch/riscv/util/header.c
tools/perf/ui/browsers/annotate.c
tools/perf/util/annotate.c
tools/perf/util/bpf_skel/lock_contention.bpf.c
tools/testing/cxl/test/cxl.c
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
tools/testing/selftests/iommu/config
tools/testing/selftests/kselftest.h
tools/testing/selftests/kselftest_harness.h
tools/testing/selftests/kvm/aarch64/vgic_init.c
tools/testing/selftests/kvm/max_guest_memory_test.c
tools/testing/selftests/kvm/set_memory_region_test.c
tools/testing/selftests/kvm/x86_64/pmu_counters_test.c
tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c
tools/testing/selftests/mm/mdwe_test.c
tools/testing/selftests/mm/protection_keys.c
tools/testing/selftests/mm/run_vmtests.sh
tools/testing/selftests/mm/split_huge_page_test.c
tools/testing/selftests/net/tcp_ao/lib/proc.c
tools/testing/selftests/net/tcp_ao/lib/setup.c
tools/testing/selftests/net/tcp_ao/rst.c
tools/testing/selftests/net/tcp_ao/setsockopt-closed.c
tools/testing/selftests/net/udpgso.c
tools/testing/selftests/powerpc/papr_vpd/papr_vpd.c
tools/testing/selftests/riscv/hwprobe/cbo.c
tools/testing/selftests/riscv/hwprobe/hwprobe.h
tools/testing/selftests/syscall_user_dispatch/sud_test.c
virt/kvm/kvm_main.c
virt/kvm/kvm_mm.h
virt/kvm/pfncache.c

index 8284692f9610715fa2bc04f8771cb45d1b5ebf88..9f41b3906b663794ca27b77730d12cba68f05c35 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -38,6 +38,16 @@ Alexei Starovoitov <ast@kernel.org> <alexei.starovoitov@gmail.com>
 Alexei Starovoitov <ast@kernel.org> <ast@fb.com>
 Alexei Starovoitov <ast@kernel.org> <ast@plumgrid.com>
 Alexey Makhalov <alexey.amakhalov@broadcom.com> <amakhalov@vmware.com>
+Alex Elder <elder@kernel.org>
+Alex Elder <elder@kernel.org> <aelder@sgi.com>
+Alex Elder <elder@kernel.org> <alex.elder@linaro.org>
+Alex Elder <elder@kernel.org> <alex.elder@linary.org>
+Alex Elder <elder@kernel.org> <elder@dreamhost.com>
+Alex Elder <elder@kernel.org> <elder@dreawmhost.com>
+Alex Elder <elder@kernel.org> <elder@ieee.org>
+Alex Elder <elder@kernel.org> <elder@inktank.com>
+Alex Elder <elder@kernel.org> <elder@linaro.org>
+Alex Elder <elder@kernel.org> <elder@newdream.net>
 Alex Hung <alexhung@gmail.com> <alex.hung@canonical.com>
 Alex Shi <alexs@kernel.org> <alex.shi@intel.com>
 Alex Shi <alexs@kernel.org> <alex.shi@linaro.org>
@@ -98,6 +108,8 @@ Ben Widawsky <bwidawsk@kernel.org> <ben@bwidawsk.net>
 Ben Widawsky <bwidawsk@kernel.org> <ben.widawsky@intel.com>
 Ben Widawsky <bwidawsk@kernel.org> <benjamin.widawsky@intel.com>
 Benjamin Poirier <benjamin.poirier@gmail.com> <bpoirier@suse.de>
+Benjamin Tissoires <bentiss@kernel.org> <benjamin.tissoires@gmail.com>
+Benjamin Tissoires <bentiss@kernel.org> <benjamin.tissoires@redhat.com>
 Bjorn Andersson <andersson@kernel.org> <bjorn@kryo.se>
 Bjorn Andersson <andersson@kernel.org> <bjorn.andersson@linaro.org>
 Bjorn Andersson <andersson@kernel.org> <bjorn.andersson@sonymobile.com>
@@ -446,7 +458,8 @@ Mythri P K <mythripk@ti.com>
 Nadav Amit <nadav.amit@gmail.com> <namit@vmware.com>
 Nadav Amit <nadav.amit@gmail.com> <namit@cs.technion.ac.il>
 Nadia Yvette Chambers <nyc@holomorphy.com> William Lee Irwin III <wli@holomorphy.com>
-Naoya Horiguchi <naoya.horiguchi@nec.com> <n-horiguchi@ah.jp.nec.com>
+Naoya Horiguchi <nao.horiguchi@gmail.com> <n-horiguchi@ah.jp.nec.com>
+Naoya Horiguchi <nao.horiguchi@gmail.com> <naoya.horiguchi@nec.com>
 Nathan Chancellor <nathan@kernel.org> <natechancellor@gmail.com>
 Neeraj Upadhyay <quic_neeraju@quicinc.com> <neeraju@codeaurora.org>
 Neil Armstrong <neil.armstrong@linaro.org> <narmstrong@baylibre.com>
@@ -499,6 +512,7 @@ Praveen BP <praveenbp@ti.com>
 Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com> <pradeepc@codeaurora.org>
 Prasad Sodagudi <quic_psodagud@quicinc.com> <psodagud@codeaurora.org>
 Punit Agrawal <punitagrawal@gmail.com> <punit.agrawal@arm.com>
+Puranjay Mohan <puranjay@kernel.org> <puranjay12@gmail.com>
 Qais Yousef <qyousef@layalina.io> <qais.yousef@imgtec.com>
 Qais Yousef <qyousef@layalina.io> <qais.yousef@arm.com>
 Quentin Monnet <qmo@kernel.org> <quentin.monnet@netronome.com>
@@ -524,6 +538,7 @@ Rémi Denis-Courmont <rdenis@simphalempin.com>
 Ricardo Ribalda <ribalda@kernel.org> <ricardo@ribalda.com>
 Ricardo Ribalda <ribalda@kernel.org> Ricardo Ribalda Delgado <ribalda@kernel.org>
 Ricardo Ribalda <ribalda@kernel.org> <ricardo.ribalda@gmail.com>
+Richard Genoud <richard.genoud@bootlin.com> <richard.genoud@gmail.com>
 Richard Leitner <richard.leitner@linux.dev> <dev@g0hl1n.net>
 Richard Leitner <richard.leitner@linux.dev> <me@g0hl1n.net>
 Richard Leitner <richard.leitner@linux.dev> <richard.leitner@skidata.com>
index 902ecd92a29fbe83df18d32d1a8fe652c8277132..213d0719e2b7a68e4daa12482a4c60361e19e3c4 100644 (file)
                        arch-independent options, each of which is an
                        aggregation of existing arch-specific options.
 
+                       Note, "mitigations" is supported if and only if the
+                       kernel was built with CPU_MITIGATIONS=y.
+
                        off
                                Disable all optional CPU mitigations.  This
                                improves system performance, but it may also
index d3504826f401541e1dd4946c3f6d9f55989bee46..c389d4fd7599df2a8003365ee7df3d12793fae16 100644 (file)
@@ -29,7 +29,7 @@ The essence of the process (aka 'TL;DR')
 ========================================
 
 *[If you are new to building or bisecting Linux, ignore this section and head
-over to the* ":ref:`step-by-step guide<introguide_bissbs>`" *below. It utilizes
+over to the* ':ref:`step-by-step guide <introguide_bissbs>`' *below. It utilizes
 the same commands as this section while describing them in brief fashion. The
 steps are nevertheless easy to follow and together with accompanying entries
 in a reference section mention many alternatives, pitfalls, and additional
@@ -38,8 +38,8 @@ aspects, all of which might be essential in your present case.]*
 **In case you want to check if a bug is present in code currently supported by
 developers**, execute just the *preparations* and *segment 1*; while doing so,
 consider the newest Linux kernel you regularly use to be the 'working' kernel.
-In the following example that's assumed to be 6.0.13, which is why the sources
-of 6.0 will be used to prepare the .config file.
+In the following example that's assumed to be 6.0, which is why its sources
+will be used to prepare the .config file.
 
 **In case you face a regression**, follow the steps at least till the end of
 *segment 2*. Then you can submit a preliminary report -- or continue with
@@ -61,7 +61,7 @@ will be considered the 'good' release and used to prepare the .config file.
     cd ~/linux/
     git remote add -t master stable \
       https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
-    git checkout --detach v6.0
+    git switch --detach v6.0
     # * Hint: if you used an existing clone, ensure no stale .config is around.
     make olddefconfig
     # * Ensure the former command picked the .config of the 'working' kernel.
@@ -87,7 +87,7 @@ will be considered the 'good' release and used to prepare the .config file.
   a) Checking out latest mainline code::
 
        cd ~/linux/
-       git checkout --force --detach mainline/master
+       git switch --discard-changes --detach mainline/master
 
   b) Build, install, and boot a kernel::
 
@@ -125,7 +125,7 @@ will be considered the 'good' release and used to prepare the .config file.
   a) Start by checking out the sources of the 'good' version::
 
        cd ~/linux/
-       git checkout --force --detach v6.0
+       git switch --discard-changes --detach v6.0
 
   b) Build, install, and boot a kernel as described earlier in *segment 1,
      section b* -- just feel free to skip the 'du' commands, as you have a rough
@@ -136,8 +136,7 @@ will be considered the 'good' release and used to prepare the .config file.
 
 * **Segment 3**: perform and validate the bisection.
 
-  a) In case your 'broken' version is a stable/longterm release, add the Git
-     branch holding it::
+  a) Retrieve the sources for your 'bad' version::
 
        git remote set-branches --add stable linux-6.1.y
        git fetch stable
@@ -157,11 +156,12 @@ will be considered the 'good' release and used to prepare the .config file.
      works with the newly built kernel. If it does, tell Git by executing
      ``git bisect good``; if it does not, run ``git bisect bad`` instead.
 
-     All three commands will make Git checkout another commit; then re-execute
+     All three commands will make Git check out another commit; then re-execute
      this step (e.g. build, install, boot, and test a kernel to then tell Git
      the outcome). Do so again and again until Git shows which commit broke
      things. If you run short of disk space during this process, check the
-     "Supplementary tasks" section below.
+     section 'Complementary tasks: cleanup during and after the process'
+     below.
 
   d) Once your finished the bisection, put a few things away::
 
@@ -172,14 +172,17 @@ will be considered the 'good' release and used to prepare the .config file.
 
   e) Try to verify the bisection result::
 
-       git checkout --force --detach mainline/master
+       git switch --discard-changes --detach mainline/master
        git revert --no-edit cafec0cacaca0
+       cp ~/kernel-config-working .config
+       ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted'
 
     This is optional, as some commits are impossible to revert. But if the
     second command worked flawlessly, build, install, and boot one more kernel
-    kernel, which should not show the regression.
+    kernel; just this time skip the first command copying the base .config file
+    over, as that already has been taken care off.
 
-* **Supplementary tasks**: cleanup during and after the process.
+* **Complementary tasks**: cleanup during and after the process.
 
   a) To avoid running out of disk space during a bisection, you might need to
      remove some kernels you built earlier. You most likely want to keep those
@@ -202,13 +205,25 @@ will be considered the 'good' release and used to prepare the .config file.
      the kernels you built earlier and later you might want to keep around for
      a week or two.
 
+* **Optional task**: test a debug patch or a proposed fix later::
+
+    git fetch mainline
+    git switch --discard-changes --detach mainline/master
+    git apply /tmp/foobars-proposed-fix-v1.patch
+    cp ~/kernel-config-working .config
+    ./scripts/config --set-str CONFIG_LOCALVERSION '-local-foobars-fix-v1'
+
+  Build, install, and boot a kernel as described in *segment 1, section b* --
+  but this time omit the first command copying the build configuration over,
+  as that has been taken care of already.
+
 .. _introguide_bissbs:
 
 Step-by-step guide on how to verify bugs and bisect regressions
 ===============================================================
 
 This guide describes how to set up your own Linux kernels for investigating bugs
-or regressions you intent to report. How far you want to follow the instructions
+or regressions you intend to report. How far you want to follow the instructions
 depends on your issue:
 
 Execute all steps till the end of *segment 1* to **verify if your kernel problem
@@ -221,15 +236,17 @@ report; instead of the latter your could also head straight on and follow
 *segment 3* to **perform a bisection** for a full-fledged regression report
 developers are obliged to act upon.
 
- :ref:`Preparations: set up everything to build your own kernels.<introprep_bissbs>`
+ :ref:`Preparations: set up everything to build your own kernels <introprep_bissbs>`.
 
- :ref:`Segment 1: try to reproduce the problem with the latest codebase.<introlatestcheck_bissbs>`
+ :ref:`Segment 1: try to reproduce the problem with the latest codebase <introlatestcheck_bissbs>`.
 
- :ref:`Segment 2: check if the kernels you build work fine.<introworkingcheck_bissbs>`
+ :ref:`Segment 2: check if the kernels you build work fine <introworkingcheck_bissbs>`.
 
- :ref:`Segment 3: perform a bisection and validate the result.<introbisect_bissbs>`
+ :ref:`Segment 3: perform a bisection and validate the result <introbisect_bissbs>`.
 
- :ref:`Supplementary tasks: cleanup during and after following this guide.<introclosure_bissbs>`
+ :ref:`Complementary tasks: cleanup during and after following this guide <introclosure_bissbs>`.
+
+ :ref:`Optional tasks: test reverts, patches, or later versions <introoptional_bissbs>`.
 
 The steps in each segment illustrate the important aspects of the process, while
 a comprehensive reference section holds additional details for almost all of the
@@ -240,24 +257,35 @@ to get things rolling again.
 For further details on how to report Linux kernel issues or regressions check
 out Documentation/admin-guide/reporting-issues.rst, which works in conjunction
 with this document. It among others explains why you need to verify bugs with
-the latest 'mainline' kernel, even if you face a problem with a kernel from a
-'stable/longterm' series; for users facing a regression it also explains that
-sending a preliminary report after finishing segment 2 might be wise, as the
-regression and its culprit might be known already. For further details on
-what actually qualifies as a regression check out
-Documentation/admin-guide/reporting-regressions.rst.
+the latest 'mainline' kernel (e.g. versions like 6.0, 6.1-rc1, or 6.1-rc6),
+even if you face a problem with a kernel from a 'stable/longterm' series
+(say 6.0.13).
+
+For users facing a regression that document also explains why sending a
+preliminary report after segment 2 might be wise, as the regression and its
+culprit might be known already. For further details on what actually qualifies
+as a regression check out Documentation/admin-guide/reporting-regressions.rst.
+
+If you run into any problems while following this guide or have ideas how to
+improve it, :ref:`please let the kernel developers know <submit_improvements>`.
 
 .. _introprep_bissbs:
 
 Preparations: set up everything to build your own kernels
 ---------------------------------------------------------
 
+The following steps lay the groundwork for all further tasks.
+
+Note: the instructions assume you are building and testing on the same
+machine; if you want to compile the kernel on another system, check
+:ref:`Build kernels on a different machine <buildhost_bis>` below.
+
 .. _backup_bissbs:
 
 * Create a fresh backup and put system repair and restore tools at hand, just
   to be prepared for the unlikely case of something going sideways.
 
-  [:ref:`details<backup_bisref>`]
+  [:ref:`details <backup_bisref>`]
 
 .. _vanilla_bissbs:
 
@@ -265,7 +293,7 @@ Preparations: set up everything to build your own kernels
   builds them automatically. That includes but is not limited to DKMS, openZFS,
   VirtualBox, and Nvidia's graphics drivers (including the GPLed kernel module).
 
-  [:ref:`details<vanilla_bisref>`]
+  [:ref:`details <vanilla_bisref>`]
 
 .. _secureboot_bissbs:
 
@@ -276,48 +304,49 @@ Preparations: set up everything to build your own kernels
   their restrictions through a process initiated by
   ``mokutil --disable-validation``.
 
-  [:ref:`details<secureboot_bisref>`]
+  [:ref:`details <secureboot_bisref>`]
 
 .. _rangecheck_bissbs:
 
 * Determine the kernel versions considered 'good' and 'bad' throughout this
-  guide.
+  guide:
 
-  Do you follow this guide to verify if a bug is present in the code developers
-  care for? Then consider the mainline release your 'working' kernel (the newest
-  one you regularly use) is based on to be the 'good' version; if your 'working'
-  kernel for example is 6.0.11, then your 'good' kernel is 6.0.
+  * Do you follow this guide to verify if a bug is present in the code the
+    primary developers care for? Then consider the version of the newest kernel
+    you regularly use currently as 'good' (e.g. 6.0, 6.0.13, or 6.1-rc2).
 
-  In case you face a regression, it depends on the version range where the
-  regression was introduced:
+  * Do you face a regression, e.g. something broke or works worse after
+    switching to a newer kernel version? In that case it depends on the version
+    range during which the problem appeared:
 
-  * Something which used to work in Linux 6.0 broke when switching to Linux
-    6.1-rc1? Then henceforth regard 6.0 as the last known 'good' version
-    and 6.1-rc1 as the first 'bad' one.
+    * Something regressed when updating from a stable/longterm release
+      (say 6.0.13) to a newer mainline series (like 6.1-rc7 or 6.1) or a
+      stable/longterm version based on one (say 6.1.5)? Then consider the
+      mainline release your working kernel is based on to be the 'good'
+      version (e.g. 6.0) and the first version to be broken as the 'bad' one
+      (e.g. 6.1-rc7, 6.1, or 6.1.5). Note, at this point it is merely assumed
+      that 6.0 is fine; this hypothesis will be checked in segment 2.
 
-  * Some function stopped working when updating from 6.0.11 to 6.1.4? Then for
-    the time being consider 6.0 as the last 'good' version and 6.1.4 as
-    the 'bad' one. Note, at this point it is merely assumed that 6.0 is fine;
-    this assumption will be checked in segment 2.
+    * Something regressed when switching from one mainline version (say 6.0) to
+      a later one (like 6.1-rc1) or a stable/longterm release based on it
+      (say 6.1.5)? Then regard the last working version (e.g. 6.0) as 'good' and
+      the first broken (e.g. 6.1-rc1 or 6.1.5) as 'bad'.
 
-  * A feature you used in 6.0.11 does not work at all or worse in 6.1.13? In
-    that case you want to bisect within a stable/longterm series: consider
-    6.0.11 as the last known 'good' version and 6.0.13 as the first 'bad'
-    one. Note, in this case you still want to compile and test a mainline kernel
-    as explained in segment 1: the outcome will determine if you need to report
-    your issue to the regular developers or the stable team.
+    * Something regressed when updating within a stable/longterm series (say
+      from 6.0.13 to 6.0.15)? Then consider those versions as 'good' and 'bad'
+      (e.g. 6.0.13 and 6.0.15), as you need to bisect within that series.
 
   *Note, do not confuse 'good' version with 'working' kernel; the latter term
   throughout this guide will refer to the last kernel that has been working
   fine.*
 
-  [:ref:`details<rangecheck_bisref>`]
+  [:ref:`details <rangecheck_bisref>`]
 
 .. _bootworking_bissbs:
 
 * Boot into the 'working' kernel and briefly use the apparently broken feature.
 
-  [:ref:`details<bootworking_bisref>`]
+  [:ref:`details <bootworking_bisref>`]
 
 .. _diskspace_bissbs:
 
@@ -327,7 +356,7 @@ Preparations: set up everything to build your own kernels
   debug symbols: both explain approaches reducing the amount of space, which
   should allow you to master these tasks with about 4 Gigabytes free space.
 
-  [:ref:`details<diskspace_bisref>`]
+  [:ref:`details <diskspace_bisref>`]
 
 .. _buildrequires_bissbs:
 
@@ -337,7 +366,7 @@ Preparations: set up everything to build your own kernels
   reference section shows how to quickly install those on various popular Linux
   distributions.
 
-  [:ref:`details<buildrequires_bisref>`]
+  [:ref:`details <buildrequires_bisref>`]
 
 .. _sources_bissbs:
 
@@ -360,14 +389,23 @@ Preparations: set up everything to build your own kernels
     git remote add -t master stable \
       https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
 
-  [:ref:`details<sources_bisref>`]
+  [:ref:`details <sources_bisref>`]
+
+.. _stablesources_bissbs:
+
+* Is one of the versions you earlier established as 'good' or 'bad' a stable or
+  longterm release (say 6.1.5)? Then download the code for the series it belongs
+  to ('linux-6.1.y' in this example)::
+
+    git remote set-branches --add stable linux-6.1.y
+    git fetch stable
 
 .. _oldconfig_bissbs:
 
 * Start preparing a kernel build configuration (the '.config' file).
 
   Before doing so, ensure you are still running the 'working' kernel an earlier
-  step told you to boot; if you are unsure, check the current kernel release
+  step told you to boot; if you are unsure, check the current kernelrelease
   identifier using ``uname -r``.
 
   Afterwards check out the source code for the version earlier established as
@@ -375,7 +413,7 @@ Preparations: set up everything to build your own kernels
   the version number in this and all later Git commands needs to be prefixed
   with a 'v'::
 
-    git checkout --detach v6.0
+    git switch --discard-changes --detach v6.0
 
   Now create a build configuration file::
 
@@ -398,7 +436,7 @@ Preparations: set up everything to build your own kernels
   'make olddefconfig' again and check if it now picked up the right config file
   as base.
 
-  [:ref:`details<oldconfig_bisref>`]
+  [:ref:`details <oldconfig_bisref>`]
 
 .. _localmodconfig_bissbs:
 
@@ -432,7 +470,7 @@ Preparations: set up everything to build your own kernels
   spending much effort on, as long as it boots and allows to properly test the
   feature that causes trouble.
 
-  [:ref:`details<localmodconfig_bisref>`]
+  [:ref:`details <localmodconfig_bisref>`]
 
 .. _tagging_bissbs:
 
@@ -442,7 +480,7 @@ Preparations: set up everything to build your own kernels
     ./scripts/config --set-str CONFIG_LOCALVERSION '-local'
     ./scripts/config -e CONFIG_LOCALVERSION_AUTO
 
-  [:ref:`details<tagging_bisref>`]
+  [:ref:`details <tagging_bisref>`]
 
 .. _debugsymbols_bissbs:
 
@@ -461,7 +499,7 @@ Preparations: set up everything to build your own kernels
     ./scripts/config -d DEBUG_INFO -d DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT \
       -d DEBUG_INFO_DWARF4 -d DEBUG_INFO_DWARF5 -e CONFIG_DEBUG_INFO_NONE
 
-  [:ref:`details<debugsymbols_bisref>`]
+  [:ref:`details <debugsymbols_bisref>`]
 
 .. _configmods_bissbs:
 
@@ -471,14 +509,14 @@ Preparations: set up everything to build your own kernels
   * Are you running Debian? Then you want to avoid known problems by performing
     additional adjustments explained in the reference section.
 
-    [:ref:`details<configmods_distros_bisref>`].
+    [:ref:`details <configmods_distros_bisref>`].
 
   * If you want to influence other aspects of the configuration, do so now using
     your preferred tool. Note, to use make targets like 'menuconfig' or
     'nconfig', you will need to install the development files of ncurses; for
     'xconfig' you likewise need the Qt5 or Qt6 headers.
 
-    [:ref:`details<configmods_individual_bisref>`].
+    [:ref:`details <configmods_individual_bisref>`].
 
 .. _saveconfig_bissbs:
 
@@ -488,7 +526,7 @@ Preparations: set up everything to build your own kernels
      make olddefconfig
      cp .config ~/kernel-config-working
 
-  [:ref:`details<saveconfig_bisref>`]
+  [:ref:`details <saveconfig_bisref>`]
 
 .. _introlatestcheck_bissbs:
 
@@ -498,16 +536,30 @@ Segment 1: try to reproduce the problem with the latest codebase
 The following steps verify if the problem occurs with the code currently
 supported by developers. In case you face a regression, it also checks that the
 problem is not caused by some .config change, as reporting the issue then would
-be a waste of time. [:ref:`details<introlatestcheck_bisref>`]
+be a waste of time. [:ref:`details <introlatestcheck_bisref>`]
 
 .. _checkoutmaster_bissbs:
 
-* Check out the latest Linux codebase::
+* Check out the latest Linux codebase.
 
-    cd ~/linux/
-    git checkout --force --detach mainline/master
+  * Are your 'good' and 'bad' versions from the same stable or longterm series?
+    Then check the `front page of kernel.org <https://kernel.org/>`_: if it
+    lists a release from that series without an '[EOL]' tag, checkout the series
+    latest version ('linux-6.1.y' in the following example)::
+
+      cd ~/linux/
+      git switch --discard-changes --detach stable/linux-6.1.y
+
+    Your series is unsupported, if is not listed or carrying a 'end of life'
+    tag. In that case you might want to check if a successor series (say
+    linux-6.2.y) or mainline (see next point) fix the bug.
 
-  [:ref:`details<checkoutmaster_bisref>`]
+  * In all other cases, run::
+
+      cd ~/linux/
+      git switch --discard-changes --detach mainline/master
+
+  [:ref:`details <checkoutmaster_bisref>`]
 
 .. _build_bissbs:
 
@@ -522,7 +574,7 @@ be a waste of time. [:ref:`details<introlatestcheck_bisref>`]
   reference section for alternatives, which obviously will require other
   steps to install as well.
 
-  [:ref:`details<build_bisref>`]
+  [:ref:`details <build_bisref>`]
 
 .. _install_bissbs:
 
@@ -555,7 +607,7 @@ be a waste of time. [:ref:`details<introlatestcheck_bisref>`]
   down: if you will build more kernels as described in segment 2 and 3, you will
   have to perform those again after executing ``command -v installkernel [...]``.
 
-  [:ref:`details<install_bisref>`]
+  [:ref:`details <install_bisref>`]
 
 .. _storagespace_bissbs:
 
@@ -568,7 +620,7 @@ be a waste of time. [:ref:`details<introlatestcheck_bisref>`]
   Write down or remember those two values for later: they enable you to prevent
   running out of disk space accidentally during a bisection.
 
-  [:ref:`details<storagespace_bisref>`]
+  [:ref:`details <storagespace_bisref>`]
 
 .. _kernelrelease_bissbs:
 
@@ -595,7 +647,7 @@ be a waste of time. [:ref:`details<introlatestcheck_bisref>`]
   If that command does not return '0', check the reference section, as the cause
   for this might interfere with your testing.
 
-  [:ref:`details<tainted_bisref>`]
+  [:ref:`details <tainted_bisref>`]
 
 .. _recheckbroken_bissbs:
 
@@ -603,21 +655,19 @@ be a waste of time. [:ref:`details<introlatestcheck_bisref>`]
   out the instructions in the reference section to ensure nothing went sideways
   during your tests.
 
-  [:ref:`details<recheckbroken_bisref>`]
+  [:ref:`details <recheckbroken_bisref>`]
 
 .. _recheckstablebroken_bissbs:
 
-* Are you facing a problem within a stable/longterm series, but failed to
-  reproduce it with the mainline kernel you just built? One that according to
-  the `front page of kernel.org <https://kernel.org/>`_ is still supported? Then
-  check if the latest codebase for the particular series might already fix the
-  problem. To do so, add the stable series Git branch for your 'good' kernel
-  (again, this here is assumed to be 6.0) and check out the latest version::
+* Did you just built a stable or longterm kernel? And were you able to reproduce
+  the regression with it? Then you should test the latest mainline codebase as
+  well, because the result determines which developers the bug must be submitted
+  to.
+
+  To prepare that test, check out current mainline::
 
     cd ~/linux/
-    git remote set-branches --add stable linux-6.0.y
-    git fetch stable
-    git checkout --force --detach linux-6.0.y
+    git switch --discard-changes --detach mainline/master
 
   Now use the checked out code to build and install another kernel using the
   commands the earlier steps already described in more detail::
@@ -639,14 +689,16 @@ be a waste of time. [:ref:`details<introlatestcheck_bisref>`]
     uname -r
     cat /proc/sys/kernel/tainted
 
-  Now verify if this kernel is showing the problem.
+  Now verify if this kernel is showing the problem. If it does, then you need
+  to report the bug to the primary developers; if it does not, report it to the
+  stable team. See Documentation/admin-guide/reporting-issues.rst for details.
 
-  [:ref:`details<recheckstablebroken_bisref>`]
+  [:ref:`details <recheckstablebroken_bisref>`]
 
 Do you follow this guide to verify if a problem is present in the code
 currently supported by Linux kernel developers? Then you are done at this
 point. If you later want to remove the kernel you just built, check out
-:ref:`Supplementary tasks: cleanup during and after following this guide<introclosure_bissbs>`.
+:ref:`Complementary tasks: cleanup during and after following this guide <introclosure_bissbs>`.
 
 In case you face a regression, move on and execute at least the next segment
 as well.
@@ -658,7 +710,7 @@ Segment 2: check if the kernels you build work fine
 
 In case of a regression, you now want to ensure the trimmed configuration file
 you created earlier works as expected; a bisection with the .config file
-otherwise would be a waste of time. [:ref:`details<introworkingcheck_bisref>`]
+otherwise would be a waste of time. [:ref:`details <introworkingcheck_bisref>`]
 
 .. _recheckworking_bissbs:
 
@@ -669,7 +721,7 @@ otherwise would be a waste of time. [:ref:`details<introworkingcheck_bisref>`]
   'good' (once again assumed to be 6.0 here)::
 
     cd ~/linux/
-    git checkout --detach v6.0
+    git switch --discard-changes --detach v6.0
 
   Now use the checked out code to configure, build, and install another kernel
   using the commands the previous subsection explained in more detail::
@@ -693,7 +745,7 @@ otherwise would be a waste of time. [:ref:`details<introworkingcheck_bisref>`]
   Now check if this kernel works as expected; if not, consult the reference
   section for further instructions.
 
-  [:ref:`details<recheckworking_bisref>`]
+  [:ref:`details <recheckworking_bisref>`]
 
 .. _introbisect_bissbs:
 
@@ -703,18 +755,11 @@ Segment 3: perform the bisection and validate the result
 With all the preparations and precaution builds taken care of, you are now ready
 to begin the bisection. This will make you build quite a few kernels -- usually
 about 15 in case you encountered a regression when updating to a newer series
-(say from 6.0.11 to 6.1.3). But do not worry, due to the trimmed build
+(say from 6.0.13 to 6.1.5). But do not worry, due to the trimmed build
 configuration created earlier this works a lot faster than many people assume:
 overall on average it will often just take about 10 to 15 minutes to compile
 each kernel on commodity x86 machines.
 
-* In case your 'bad' version is a stable/longterm release (say 6.1.5), add its
-  stable branch, unless you already did so earlier::
-
-    cd ~/linux/
-    git remote set-branches --add stable linux-6.1.y
-    git fetch stable
-
 .. _bisectstart_bissbs:
 
 * Start the bisection and tell Git about the versions earlier established as
@@ -725,7 +770,7 @@ each kernel on commodity x86 machines.
     git bisect good v6.0
     git bisect bad v6.1.5
 
-  [:ref:`details<bisectstart_bisref>`]
+  [:ref:`details <bisectstart_bisref>`]
 
 .. _bisectbuild_bissbs:
 
@@ -745,7 +790,7 @@ each kernel on commodity x86 machines.
   If compilation fails for some reason, run ``git bisect skip`` and restart
   executing the stack of commands from the beginning.
 
-  In case you skipped the "test latest codebase" step in the guide, check its
+  In case you skipped the 'test latest codebase' step in the guide, check its
   description as for why the 'df [...]' and 'make -s kernelrelease [...]'
   commands are here.
 
@@ -754,7 +799,7 @@ each kernel on commodity x86 machines.
   totally normal to see release identifiers like '6.0-rc1-local-gcafec0cacaca0'
   if you bisect between versions 6.1 and 6.2 for example.
 
-  [:ref:`details<bisectbuild_bisref>`]
+  [:ref:`details <bisectbuild_bisref>`]
 
 .. _bisecttest_bissbs:
 
@@ -794,7 +839,7 @@ each kernel on commodity x86 machines.
   might need to scroll up to see the message mentioning the culprit;
   alternatively, run ``git bisect log > ~/bisection-log``.
 
-  [:ref:`details<bisecttest_bisref>`]
+  [:ref:`details <bisecttest_bisref>`]
 
 .. _bisectlog_bissbs:
 
@@ -806,7 +851,7 @@ each kernel on commodity x86 machines.
     cp .config ~/bisection-config-culprit
     git bisect reset
 
-  [:ref:`details<bisectlog_bisref>`]
+  [:ref:`details <bisectlog_bisref>`]
 
 .. _revert_bissbs:
 
@@ -823,16 +868,16 @@ each kernel on commodity x86 machines.
   Begin by checking out the latest codebase depending on the range you bisected:
 
   * Did you face a regression within a stable/longterm series (say between
-    6.0.11 and 6.0.13) that does not happen in mainline? Then check out the
+    6.0.13 and 6.0.15) that does not happen in mainline? Then check out the
     latest codebase for the affected series like this::
 
       git fetch stable
-      git checkout --force --detach linux-6.0.y
+      git switch --discard-changes --detach linux-6.0.y
 
   * In all other cases check out latest mainline::
 
       git fetch mainline
-      git checkout --force --detach mainline/master
+      git switch --discard-changes --detach mainline/master
 
     If you bisected a regression within a stable/longterm series that also
     happens in mainline, there is one more thing to do: look up the mainline
@@ -846,27 +891,33 @@ each kernel on commodity x86 machines.
 
     git revert --no-edit cafec0cacaca0
 
-  If that fails, give up trying and move on to the next step. But if it works,
-  build a kernel again using the familiar command sequence::
+  If that fails, give up trying and move on to the next step; if it works,
+  adjust the tag to facilitate the identification and prevent accidentally
+  overwriting another kernel::
 
     cp ~/kernel-config-working .config
+    ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted'
+
+  Build a kernel using the familiar command sequence, just without copying the
+  the base .config over::
+
     make olddefconfig &&
-    make -j $(nproc --all) &&
+    make -j $(nproc --all)
     # * Check if the free space suffices holding another kernel:
     df -h /boot/ /lib/modules/
     sudo make modules_install
     command -v installkernel && sudo make install
-    Make -s kernelrelease | tee -a ~/kernels-built
+    make -s kernelrelease | tee -a ~/kernels-built
     reboot
 
-  Now check one last time if the feature that made you perform a bisection work
-  with that kernel.
+  Now check one last time if the feature that made you perform a bisection works
+  with that kernel: if everything went well, it should not show the regression.
 
-  [:ref:`details<revert_bisref>`]
+  [:ref:`details <revert_bisref>`]
 
 .. _introclosure_bissbs:
 
-Supplementary tasks: cleanup during and after the bisection
+Complementary tasks: cleanup during and after the bisection
 -----------------------------------------------------------
 
 During and after following this guide you might want or need to remove some of
@@ -903,7 +954,7 @@ space might run out.
   kernel image and related files behind; in that case remove them as described
   in the reference section.
 
-  [:ref:`details<makeroom_bisref>`]
+  [:ref:`details <makeroom_bisref>`]
 
 .. _finishingtouch_bissbs:
 
@@ -926,18 +977,99 @@ space might run out.
     the version considered 'good', and the last three or four you compiled
     during the actual bisection process.
 
-  [:ref:`details<finishingtouch_bisref>`]
+  [:ref:`details <finishingtouch_bisref>`]
+
+.. _introoptional_bissbs:
+
+Optional: test reverts, patches, or later versions
+--------------------------------------------------
+
+While or after reporting a bug, you might want or potentially will be asked to
+test reverts, debug patches, proposed fixes, or other versions. In that case
+follow these instructions.
+
+* Update your Git clone and check out the latest code.
+
+  * In case you want to test mainline, fetch its latest changes before checking
+    its code out::
+
+      git fetch mainline
+      git switch --discard-changes --detach mainline/master
+
+  * In case you want to test a stable or longterm kernel, first add the branch
+    holding the series you are interested in (6.2 in the example), unless you
+    already did so earlier::
+
+      git remote set-branches --add stable linux-6.2.y
+
+    Then fetch the latest changes and check out the latest version from the
+    series::
+
+      git fetch stable
+      git switch --discard-changes --detach stable/linux-6.2.y
+
+* Copy your kernel build configuration over::
+
+    cp ~/kernel-config-working .config
+
+* Your next step depends on what you want to do:
+
+  * In case you just want to test the latest codebase, head to the next step,
+    you are already all set.
+
+  * In case you want to test if a revert fixes an issue, revert one or multiple
+    changes by specifying their commit ids::
+
+      git revert --no-edit cafec0cacaca0
+
+    Now give that kernel a special tag to facilitates its identification and
+    prevent accidentally overwriting another kernel::
+
+      ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted'
+
+  * In case you want to test a patch, store the patch in a file like
+    '/tmp/foobars-proposed-fix-v1.patch' and apply it like this::
+
+      git apply /tmp/foobars-proposed-fix-v1.patch
+
+    In case of multiple patches, repeat this step with the others.
+
+    Now give that kernel a special tag to facilitates its identification and
+    prevent accidentally overwriting another kernel::
+
+    ./scripts/config --set-str CONFIG_LOCALVERSION '-local-foobars-fix-v1'
+
+* Build a kernel using the familiar commands, just without copying the kernel
+  build configuration over, as that has been taken care of already::
+
+    make olddefconfig &&
+    make -j $(nproc --all)
+    # * Check if the free space suffices holding another kernel:
+    df -h /boot/ /lib/modules/
+    sudo make modules_install
+    command -v installkernel && sudo make install
+    make -s kernelrelease | tee -a ~/kernels-built
+    reboot
+
+* Now verify you booted the newly built kernel and check it.
+
+[:ref:`details <introoptional_bisref>`]
 
 .. _submit_improvements:
 
-This concludes the step-by-step guide.
+Conclusion
+----------
+
+You have reached the end of the step-by-step guide.
 
 Did you run into trouble following any of the above steps not cleared up by the
 reference section below? Did you spot errors? Or do you have ideas how to
-improve the guide? Then please take a moment and let the maintainer of this
+improve the guide?
+
+If any of that applies, please take a moment and let the maintainer of this
 document know by email (Thorsten Leemhuis <linux@leemhuis.info>), ideally while
 CCing the Linux docs mailing list (linux-doc@vger.kernel.org). Such feedback is
-vital to improve this document further, which is in everybody's interest, as it
+vital to improve this text further, which is in everybody's interest, as it
 will enable more people to master the task described here -- and hopefully also
 improve similar guides inspired by this one.
 
@@ -948,10 +1080,20 @@ Reference section for the step-by-step guide
 This section holds additional information for almost all the items in the above
 step-by-step guide.
 
+Preparations for building your own kernels
+------------------------------------------
+
+  *The steps in this section lay the groundwork for all further tests.*
+  [:ref:`... <introprep_bissbs>`]
+
+The steps in all later sections of this guide depend on those described here.
+
+[:ref:`back to step-by-step guide <introprep_bissbs>`].
+
 .. _backup_bisref:
 
 Prepare for emergencies
------------------------
+~~~~~~~~~~~~~~~~~~~~~~~
 
   *Create a fresh backup and put system repair and restore tools at hand.*
   [:ref:`... <backup_bissbs>`]
@@ -966,7 +1108,7 @@ for something going sideways, even if that should not happen.
 .. _vanilla_bisref:
 
 Remove anything related to externally maintained kernel modules
----------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Remove all software that depends on externally developed kernel drivers or
   builds them automatically.* [:ref:`...<vanilla_bissbs>`]
@@ -984,7 +1126,7 @@ explains in more detail.
 .. _secureboot_bisref:
 
 Deal with techniques like Secure Boot
--------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *On platforms with 'Secure Boot' or similar techniques, prepare everything to
   ensure the system will permit your self-compiled kernel to boot later.*
@@ -1021,7 +1163,7 @@ Afterwards, permit MokManager to reboot the machine.
 .. _bootworking_bisref:
 
 Boot the last kernel that was working
--------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Boot into the last working kernel and briefly recheck if the feature that
   regressed really works.* [:ref:`...<bootworking_bissbs>`]
@@ -1034,7 +1176,7 @@ the right thing.
 .. _diskspace_bisref:
 
 Space requirements
-------------------
+~~~~~~~~~~~~~~~~~~
 
   *Ensure to have enough free space for building Linux.*
   [:ref:`... <diskspace_bissbs>`]
@@ -1052,32 +1194,32 @@ space by quite a few gigabytes.
 .. _rangecheck_bisref:
 
 Bisection range
----------------
+~~~~~~~~~~~~~~~
 
   *Determine the kernel versions considered 'good' and 'bad' throughout this
   guide.* [:ref:`...<rangecheck_bissbs>`]
 
 Establishing the range of commits to be checked is mostly straightforward,
 except when a regression occurred when switching from a release of one stable
-series to a release of a later series (e.g. from 6.0.11 to 6.1.4). In that case
+series to a release of a later series (e.g. from 6.0.13 to 6.1.5). In that case
 Git will need some hand holding, as there is no straight line of descent.
 
 That's because with the release of 6.0 mainline carried on to 6.1 while the
 stable series 6.0.y branched to the side. It's therefore theoretically possible
-that the issue you face with 6.1.4 only worked in 6.0.11, as it was fixed by a
+that the issue you face with 6.1.5 only worked in 6.0.13, as it was fixed by a
 commit that went into one of the 6.0.y releases, but never hit mainline or the
 6.1.y series. Thankfully that normally should not happen due to the way the
 stable/longterm maintainers maintain the code. It's thus pretty safe to assume
 6.0 as a 'good' kernel. That assumption will be tested anyway, as that kernel
 will be built and tested in the segment '2' of this guide; Git would force you
-to do this as well, if you tried bisecting between 6.0.11 and 6.1.13.
+to do this as well, if you tried bisecting between 6.0.13 and 6.1.15.
 
 [:ref:`back to step-by-step guide <rangecheck_bissbs>`]
 
 .. _buildrequires_bisref:
 
 Install build requirements
---------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Install all software required to build a Linux kernel.*
   [:ref:`...<buildrequires_bissbs>`]
@@ -1117,7 +1259,7 @@ These commands install a few packages that are often, but not always needed. You
 for example might want to skip installing the development headers for ncurses,
 which you will only need in case you later might want to adjust the kernel build
 configuration using make the targets 'menuconfig' or 'nconfig'; likewise omit
-the headers of Qt6 is you do not plan to adjust the .config using 'xconfig'.
+the headers of Qt6 if you do not plan to adjust the .config using 'xconfig'.
 
 You furthermore might need additional libraries and their development headers
 for tasks not covered in this guide -- for example when building utilities from
@@ -1128,7 +1270,7 @@ the kernel's tools/ directory.
 .. _sources_bisref:
 
 Download the sources using Git
-------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Retrieve the Linux mainline sources.*
   [:ref:`...<sources_bissbs>`]
@@ -1148,7 +1290,7 @@ work better for you:
 .. _sources_bundle_bisref:
 
 Downloading Linux mainline sources using a bundle
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+"""""""""""""""""""""""""""""""""""""""""""""""""
 
 Use the following commands to retrieve the Linux mainline sources using a
 bundle::
@@ -1184,7 +1326,7 @@ First, execute the following command to retrieve the latest mainline codebase::
       https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
 
 Now deepen your clone's history to the second predecessor of the mainline
-release of your 'good' version. In case the latter are 6.0 or 6.0.11, 5.19 would
+release of your 'good' version. In case the latter are 6.0 or 6.0.13, 5.19 would
 be the first predecessor and 5.18 the second -- hence deepen the history up to
 that version::
 
@@ -1219,7 +1361,7 @@ Note, shallow clones have a few peculiar characteristics:
 .. _oldconfig_bisref:
 
 Start defining the build configuration for your kernel
-------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Start preparing a kernel build configuration (the '.config' file).*
   [:ref:`... <oldconfig_bissbs>`]
@@ -1279,7 +1421,7 @@ that file to the build machine and store it as ~/linux/.config; afterwards run
 .. _localmodconfig_bisref:
 
 Trim the build configuration for your kernel
---------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Disable any kernel modules apparently superfluous for your setup.*
   [:ref:`... <localmodconfig_bissbs>`]
@@ -1328,7 +1470,7 @@ step-by-step guide mentions::
 .. _tagging_bisref:
 
 Tag the kernels about to be build
----------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Ensure all the kernels you will build are clearly identifiable using a
   special tag and a unique version identifier.* [:ref:`... <tagging_bissbs>`]
@@ -1344,7 +1486,7 @@ confusing during the bisection.
 .. _debugsymbols_bisref:
 
 Decide to enable or disable debug symbols
------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Decide how to handle debug symbols.* [:ref:`... <debugsymbols_bissbs>`]
 
@@ -1373,7 +1515,7 @@ explains this process in more detail.
 .. _configmods_bisref:
 
 Adjust build configuration
---------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Check if you may want or need to adjust some other kernel configuration
   options:*
@@ -1384,7 +1526,7 @@ kernel configuration options.
 .. _configmods_distros_bisref:
 
 Distro specific adjustments
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+"""""""""""""""""""""""""""
 
   *Are you running* [:ref:`... <configmods_bissbs>`]
 
@@ -1409,7 +1551,7 @@ when following this guide on a few commodity distributions.
 .. _configmods_individual_bisref:
 
 Individual adjustments
-~~~~~~~~~~~~~~~~~~~~~~
+""""""""""""""""""""""
 
   *If you want to influence the other aspects of the configuration, do so
   now.* [:ref:`... <configmods_bissbs>`]
@@ -1426,13 +1568,13 @@ is missing.
 .. _saveconfig_bisref:
 
 Put the .config file aside
---------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Reprocess the .config after the latest changes and store it in a safe place.*
   [:ref:`... <saveconfig_bissbs>`]
 
 Put the .config you prepared aside, as you want to copy it back to the build
-directory every time  during this guide before you start building another
+directory every time during this guide before you start building another
 kernel. That's because going back and forth between different versions can alter
 .config files in odd ways; those occasionally cause side effects that could
 confuse testing or in some cases render the result of your bisection
@@ -1442,8 +1584,8 @@ meaningless.
 
 .. _introlatestcheck_bisref:
 
-Try to reproduce the regression
------------------------------------------
+Try to reproduce the problem with the latest codebase
+-----------------------------------------------------
 
   *Verify the regression is not caused by some .config change and check if it
   still occurs with the latest codebase.* [:ref:`... <introlatestcheck_bissbs>`]
@@ -1490,28 +1632,28 @@ highly recommended for these reasons:
 
   Your report might be ignored if you send it to the wrong party -- and even
   when you get a reply there is a decent chance that developers tell you to
-  evaluate   which of the two cases it is before they take a closer look.
+  evaluate which of the two cases it is before they take a closer look.
 
 [:ref:`back to step-by-step guide <introlatestcheck_bissbs>`]
 
 .. _checkoutmaster_bisref:
 
 Check out the latest Linux codebase
------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Check out the latest Linux codebase.*
-  [:ref:`... <introlatestcheck_bissbs>`]
+  [:ref:`... <checkoutmaster_bissbs>`]
 
 In case you later want to recheck if an ever newer codebase might fix the
 problem, remember to run that ``git fetch --shallow-exclude [...]`` command
 again mentioned earlier to update your local Git repository.
 
-[:ref:`back to step-by-step guide <introlatestcheck_bissbs>`]
+[:ref:`back to step-by-step guide <checkoutmaster_bissbs>`]
 
 .. _build_bisref:
 
 Build your kernel
------------------
+~~~~~~~~~~~~~~~~~
 
   *Build the image and the modules of your first kernel using the config file
   you prepared.* [:ref:`... <build_bissbs>`]
@@ -1521,7 +1663,7 @@ yourself. Another subsection explains how to directly package your kernel up as
 deb, rpm or tar file.
 
 Dealing with build errors
-~~~~~~~~~~~~~~~~~~~~~~~~~
+"""""""""""""""""""""""""
 
 When a build error occurs, it might be caused by some aspect of your machine's
 setup that often can be fixed quickly; other times though the problem lies in
@@ -1552,11 +1694,11 @@ by modifying your search terms or using another line from the error messages.
 
 In the end, most issues you run into have likely been encountered and
 reported by others already. That includes issues where the cause is not your
-system, but lies in the code. If you run into one of those, you might thus find a
-solution (e.g. a patch) or workaround for your issue, too.
+system, but lies in the code. If you run into one of those, you might thus find
+solution (e.g. a patch) or workaround for your issue, too.
 
 Package your kernel up
-~~~~~~~~~~~~~~~~~~~~~~
+""""""""""""""""""""""
 
 The step-by-step guide uses the default make targets (e.g. 'bzImage' and
 'modules' on x86) to build the image and the modules of your kernel, which later
@@ -1587,7 +1729,7 @@ distribution's kernel packages.
 .. _install_bisref:
 
 Put the kernel in place
------------------------
+~~~~~~~~~~~~~~~~~~~~~~~
 
   *Install the kernel you just built.* [:ref:`... <install_bissbs>`]
 
@@ -1630,7 +1772,7 @@ process. Afterwards add your kernel to your bootloader configuration and reboot.
 .. _storagespace_bisref:
 
 Storage requirements per kernel
--------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Check how much storage space the kernel, its modules, and other related files
   like the initramfs consume.* [:ref:`... <storagespace_bissbs>`]
@@ -1651,7 +1793,7 @@ need to look in different places.
 .. _tainted_bisref:
 
 Check if your newly built kernel considers itself 'tainted'
------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Check if the kernel marked itself as 'tainted'.*
   [:ref:`... <tainted_bissbs>`]
@@ -1670,7 +1812,7 @@ interest, as your testing might be flawed otherwise.
 .. _recheckbroken_bisref:
 
 Check the kernel built from a recent mainline codebase
-------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Verify if your bug occurs with the newly built kernel.*
   [:ref:`... <recheckbroken_bissbs>`]
@@ -1696,7 +1838,7 @@ the kernel you built from the latest codebase. These are the most frequent:
 .. _recheckstablebroken_bisref:
 
 Check the kernel built from the latest stable/longterm codebase
----------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Are you facing a regression within a stable/longterm release, but failed to
   reproduce it with the kernel you just built using the latest mainline sources?
@@ -1741,7 +1883,7 @@ ensure the kernel version you assumed to be 'good' earlier in the process (e.g.
 .. _recheckworking_bisref:
 
 Build your own version of the 'good' kernel
--------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Build your own variant of the working kernel and check if the feature that
   regressed works as expected with it.* [:ref:`... <recheckworking_bissbs>`]
@@ -1767,15 +1909,25 @@ multitude of reasons why this might happen. Some ideas where to look:
 
 Note, if you found and fixed problems with the .config file, you want to use it
 to build another kernel from the latest codebase, as your earlier tests with
-mainline and the latest version from an affected stable/longterm series were most
-likely flawed.
+mainline and the latest version from an affected stable/longterm series were
+most likely flawed.
 
 [:ref:`back to step-by-step guide <recheckworking_bissbs>`]
 
+Perform a bisection and validate the result
+-------------------------------------------
+
+  *With all the preparations and precaution builds taken care of, you are now
+  ready to begin the bisection.* [:ref:`... <introbisect_bissbs>`]
+
+The steps in this segment perform and validate the bisection.
+
+[:ref:`back to step-by-step guide <introbisect_bissbs>`].
+
 .. _bisectstart_bisref:
 
 Start the bisection
--------------------
+~~~~~~~~~~~~~~~~~~~
 
   *Start the bisection and tell Git about the versions earlier established as
   'good' and 'bad'.* [:ref:`... <bisectstart_bissbs>`]
@@ -1789,7 +1941,7 @@ for you to test.
 .. _bisectbuild_bisref:
 
 Build a kernel from the bisection point
----------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Build, install, and boot a kernel from the code Git checked out using the
   same commands you used earlier.* [:ref:`... <bisectbuild_bissbs>`]
@@ -1817,7 +1969,7 @@ There are two things worth of note here:
 .. _bisecttest_bisref:
 
 Bisection checkpoint
---------------------
+~~~~~~~~~~~~~~~~~~~~
 
   *Check if the feature that regressed works in the kernel you just built.*
   [:ref:`... <bisecttest_bissbs>`]
@@ -1831,7 +1983,7 @@ will be for nothing.
 .. _bisectlog_bisref:
 
 Put the bisection log away
---------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Store Git's bisection log and the current .config file in a safe place.*
   [:ref:`... <bisectlog_bissbs>`]
@@ -1851,7 +2003,7 @@ ask for it after you report the regression.
 .. _revert_bisref:
 
 Try reverting the culprit
--------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Try reverting the culprit on top of the latest codebase to see if this fixes
   your regression.* [:ref:`... <revert_bissbs>`]
@@ -1869,14 +2021,20 @@ succeeds, test that kernel version instead.
 
 [:ref:`back to step-by-step guide <revert_bissbs>`]
 
+Cleanup steps during and after following this guide
+---------------------------------------------------
 
-Supplementary tasks: cleanup during and after the bisection
------------------------------------------------------------
+  *During and after following this guide you might want or need to remove some
+  of the kernels you installed.* [:ref:`... <introclosure_bissbs>`]
+
+The steps in this section describe clean-up procedures.
+
+[:ref:`back to step-by-step guide <introclosure_bissbs>`].
 
 .. _makeroom_bisref:
 
 Cleaning up during the bisection
---------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *To remove one of the kernels you installed, look up its 'kernelrelease'
   identifier.* [:ref:`... <makeroom_bissbs>`]
@@ -1911,13 +2069,13 @@ Now remove the boot entry for the kernel from your bootloader's configuration;
 the steps to do that vary quite a bit between Linux distributions.
 
 Note, be careful with wildcards like '*' when deleting files or directories
-for kernels manually: you might accidentally remove files of a 6.0.11 kernel
+for kernels manually: you might accidentally remove files of a 6.0.13 kernel
 when all you want is to remove 6.0 or 6.0.1.
 
 [:ref:`back to step-by-step guide <makeroom_bissbs>`]
 
 Cleaning up after the bisection
--------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 .. _finishingtouch_bisref:
 
@@ -1932,26 +2090,105 @@ build artifacts and the Linux sources, but will leave the Git repository
 (~/linux/.git/) behind -- a simple ``git reset --hard`` thus will bring the
 sources back.
 
-Removing the repository as well would likely be unwise at this point: there is a
-decent chance developers will ask you to build another kernel to perform
-additional tests. This is often required to debug an issue or check proposed
-fixes. Before doing so you want to run the ``git fetch mainline`` command again
-followed by ``git checkout mainline/master`` to bring your clone up to date and
-checkout the latest codebase. Then apply the patch using ``git apply
-<filename>`` or ``git am <filename>`` and build yet another kernel using the
-familiar commands.
+Removing the repository as well would likely be unwise at this point: there
+is a decent chance developers will ask you to build another kernel to
+perform additional tests -- like testing a debug patch or a proposed fix.
+Details on how to perform those can be found in the section :ref:`Optional
+tasks: test reverts, patches, or later versions <introoptional_bissbs>`.
 
 Additional tests are also the reason why you want to keep the
 ~/kernel-config-working file around for a few weeks.
 
 [:ref:`back to step-by-step guide <finishingtouch_bissbs>`]
 
+.. _introoptional_bisref:
 
-Additional reading material
-===========================
+Test reverts, patches, or later versions
+----------------------------------------
+
+  *While or after reporting a bug, you might want or potentially will be asked
+  to test reverts, patches, proposed fixes, or other versions.*
+  [:ref:`... <introoptional_bissbs>`]
+
+All the commands used in this section should be pretty straight forward, so
+there is not much to add except one thing: when setting a kernel tag as
+instructed, ensure it is not much longer than the one used in the example, as
+problems will arise if the kernelrelease identifier exceeds 63 characters.
+
+[:ref:`back to step-by-step guide <introoptional_bissbs>`].
+
+
+Additional information
+======================
+
+.. _buildhost_bis:
+
+Build kernels on a different machine
+------------------------------------
+
+To compile kernels on another system, slightly alter the step-by-step guide's
+instructions:
+
+* Start following the guide on the machine where you want to install and test
+  the kernels later.
+
+* After executing ':ref:`Boot into the working kernel and briefly use the
+  apparently broken feature <bootworking_bissbs>`', save the list of loaded
+  modules to a file using ``lsmod > ~/test-machine-lsmod``. Then locate the
+  build configuration for the running kernel (see ':ref:`Start defining the
+  build configuration for your kernel <oldconfig_bisref>`' for hints on where
+  to find it) and store it as '~/test-machine-config-working'. Transfer both
+  files to the home directory of your build host.
+
+* Continue the guide on the build host (e.g. with ':ref:`Ensure to have enough
+  free space for building [...] <diskspace_bissbs>`').
+
+* When you reach ':ref:`Start preparing a kernel build configuration[...]
+  <oldconfig_bissbs>`': before running ``make olddefconfig`` for the first time,
+  execute the following command to base your configuration on the one from the
+  test machine's 'working' kernel::
+
+    cp ~/test-machine-config-working ~/linux/.config
+
+* During the next step to ':ref:`disable any apparently superfluous kernel
+  modules <localmodconfig_bissbs>`' use the following command instead::
 
-Further sources
----------------
+    yes '' | make localmodconfig LSMOD=~/lsmod_foo-machine localmodconfig
+
+* Continue the guide, but ignore the instructions outlining how to compile,
+  install, and reboot into a kernel every time they come up. Instead build
+  like this::
+
+    cp ~/kernel-config-working .config
+    make olddefconfig &&
+    make -j $(nproc --all) targz-pkg
+
+  This will generate a gzipped tar file whose name is printed in the last
+  line shown; for example, a kernel with the kernelrelease identifier
+  '6.0.0-rc1-local-g928a87efa423' built for x86 machines usually will
+  be stored as '~/linux/linux-6.0.0-rc1-local-g928a87efa423-x86.tar.gz'.
+
+  Copy that file to your test machine's home directory.
+
+* Switch to the test machine to check if you have enough space to hold another
+  kernel. Then extract the file you transferred::
+
+    sudo tar -xvzf ~/linux-6.0.0-rc1-local-g928a87efa423-x86.tar.gz -C /
+
+  Afterwards :ref:`generate the initramfs and add the kernel to your boot
+  loader's configuration <install_bisref>`; on some distributions the following
+  command will take care of both these tasks::
+
+    sudo /sbin/installkernel 6.0.0-rc1-local-g928a87efa423 /boot/vmlinuz-6.0.0-rc1-local-g928a87efa423
+
+  Now reboot and ensure you started the intended kernel.
+
+This approach even works when building for another architecture: just install
+cross-compilers and add the appropriate parameters to every invocation of make
+(e.g. ``make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- [...]``).
+
+Additional reading material
+---------------------------
 
 * The `man page for 'git bisect' <https://git-scm.com/docs/git-bisect>`_ and
   `fighting regressions with 'git bisect' <https://git-scm.com/docs/git-bisect-lk2009.html>`_
index ed73c612174d4c99d3329cc1443b553537e049db..bcc370c876be9538c5020c6a14e8584d9090ebdf 100644 (file)
@@ -671,7 +671,7 @@ configuration, worker pools and how workqueues map to the pools: ::
   events_unbound           unbound  9  9 10 10  8
   events_freezable         percpu   0  2  4  6
   events_power_efficient   percpu   0  2  4  6
-  events_freezable_power_  percpu   0  2  4  6
+  events_freezable_pwr_ef  percpu   0  2  4  6
   rcu_gp                   percpu   0  2  4  6
   rcu_par_gp               percpu   0  2  4  6
   slub_flushwq             percpu   0  2  4  6
@@ -694,7 +694,7 @@ Use tools/workqueue/wq_monitor.py to monitor workqueue operations: ::
   events_unbound              38306     0      0.1       -       7       -       -
   events_freezable                0     0      0.0       0       0       -       -
   events_power_efficient      29598     0      0.2       0       0       -       -
-  events_freezable_power_        10     0      0.0       0       0       -       -
+  events_freezable_pwr_ef        10     0      0.0       0       0       -       -
   sock_diag_events                0     0      0.0       0       0       -       -
 
                               total  infl  CPUtime  CPUhog CMW/RPR  mayday rescued
@@ -704,7 +704,7 @@ Use tools/workqueue/wq_monitor.py to monitor workqueue operations: ::
   events_unbound              38322     0      0.1       -       7       -       -
   events_freezable                0     0      0.0       0       0       -       -
   events_power_efficient      29603     0      0.2       0       0       -       -
-  events_freezable_power_        10     0      0.0       0       0       -       -
+  events_freezable_pwr_ef        10     0      0.0       0       0       -       -
   sock_diag_events                0     0      0.0       0       0       -       -
 
   ...
index 56fc71d6a081e2efef3065fdce329411b873c803..1e9797f964108f79ae51bd80c99c18883f5e6b8a 100644 (file)
@@ -38,6 +38,7 @@ properties:
               - qcom,sc7280-cpufreq-epss
               - qcom,sc8280xp-cpufreq-epss
               - qcom,sdx75-cpufreq-epss
+              - qcom,sm4450-cpufreq-epss
               - qcom,sm6375-cpufreq-epss
               - qcom,sm8250-cpufreq-epss
               - qcom,sm8350-cpufreq-epss
@@ -133,6 +134,7 @@ allOf:
               - qcom,sc8280xp-cpufreq-epss
               - qcom,sdm670-cpufreq-hw
               - qcom,sdm845-cpufreq-hw
+              - qcom,sm4450-cpufreq-epss
               - qcom,sm6115-cpufreq-hw
               - qcom,sm6350-cpufreq-hw
               - qcom,sm6375-cpufreq-epss
index 1812ef31d5f1e941d4ae0e5a53e06f278cd55aca..3c36cd0510de8364fd3bb034fd2e9c8e32ed5b85 100644 (file)
@@ -68,14 +68,10 @@ properties:
                   pattern: cs16$
               - items:
                   pattern: c32$
-              - items:
-                  pattern: c32d-wl$
               - items:
                   pattern: cs32$
               - items:
                   pattern: c64$
-              - items:
-                  pattern: c64d-wl$
               - items:
                   pattern: cs64$
               - items:
@@ -136,6 +132,7 @@ properties:
               - renesas,r1ex24128
               - samsung,s524ad0xd1
           - const: atmel,24c128
+      - pattern: '^atmel,24c(32|64)d-wl$' # Actual vendor is st
 
   label:
     description: Descriptive name of the EEPROM.
index c13c10c8d65da26cfc7faa0517f28332a2c9d8ae..eed0df9d3a2322d9818709588ca4c335f5f689d5 100644 (file)
@@ -42,7 +42,7 @@ allOf:
       properties:
         compatible:
           contains:
-            const: maxim,max30100
+            const: maxim,max30102
     then:
       properties:
         maxim,green-led-current-microamp: false
index 51f62c3ae1947107d6dc2ee5950076f4b71af42c..ec5e424bb3c8383bbb3acc4a855753bad09d35d1 100644 (file)
@@ -13,25 +13,25 @@ maintainers:
 description: |
   For some SoCs, the CPU frequency subset and voltage value of each
   OPP varies based on the silicon variant in use. Allwinner Process
-  Voltage Scaling Tables defines the voltage and frequency value based
-  on the speedbin blown in the efuse combination. The
-  sun50i-cpufreq-nvmem driver reads the efuse value from the SoC to
-  provide the OPP framework with required information.
+  Voltage Scaling Tables define the voltage and frequency values based
+  on the speedbin blown in the efuse combination.
 
 allOf:
   - $ref: opp-v2-base.yaml#
 
 properties:
   compatible:
-    const: allwinner,sun50i-h6-operating-points
+    enum:
+      - allwinner,sun50i-h6-operating-points
+      - allwinner,sun50i-h616-operating-points
 
   nvmem-cells:
     description: |
       A phandle pointing to a nvmem-cells node representing the efuse
-      registers that has information about the speedbin that is used
+      register that has information about the speedbin that is used
       to select the right frequency/voltage value pair. Please refer
-      the for nvmem-cells bindings
-      Documentation/devicetree/bindings/nvmem/nvmem.txt and also
+      to the nvmem-cells bindings in
+      Documentation/devicetree/bindings/nvmem/nvmem.yaml and also the
       examples below.
 
   opp-shared: true
@@ -47,15 +47,18 @@ patternProperties:
     properties:
       opp-hz: true
       clock-latency-ns: true
+      opp-microvolt: true
+      opp-supported-hw:
+        maxItems: 1
+        description:
+          A single 32 bit bitmap value, representing compatible HW, one
+          bit per speed bin index.
 
     patternProperties:
       "^opp-microvolt-speed[0-9]$": true
 
     required:
       - opp-hz
-      - opp-microvolt-speed0
-      - opp-microvolt-speed1
-      - opp-microvolt-speed2
 
     unevaluatedProperties: false
 
@@ -77,58 +80,54 @@ examples:
             opp-microvolt-speed2 = <800000>;
         };
 
-        opp-720000000 {
+        opp-1080000000 {
             clock-latency-ns = <244144>; /* 8 32k periods */
-            opp-hz = /bits/ 64 <720000000>;
+            opp-hz = /bits/ 64 <1080000000>;
 
-            opp-microvolt-speed0 = <880000>;
-            opp-microvolt-speed1 = <820000>;
-            opp-microvolt-speed2 = <800000>;
+            opp-microvolt-speed0 = <1060000>;
+            opp-microvolt-speed1 = <880000>;
+            opp-microvolt-speed2 = <840000>;
         };
 
-        opp-816000000 {
+        opp-1488000000 {
             clock-latency-ns = <244144>; /* 8 32k periods */
-            opp-hz = /bits/ 64 <816000000>;
+            opp-hz = /bits/ 64 <1488000000>;
 
-            opp-microvolt-speed0 = <880000>;
-            opp-microvolt-speed1 = <820000>;
-            opp-microvolt-speed2 = <800000>;
+            opp-microvolt-speed0 = <1160000>;
+            opp-microvolt-speed1 = <1000000>;
+            opp-microvolt-speed2 = <960000>;
         };
+    };
 
-        opp-888000000 {
-            clock-latency-ns = <244144>; /* 8 32k periods */
-            opp-hz = /bits/ 64 <888000000>;
-
-            opp-microvolt-speed0 = <940000>;
-            opp-microvolt-speed1 = <820000>;
-            opp-microvolt-speed2 = <800000>;
-        };
+  - |
+    opp-table {
+        compatible = "allwinner,sun50i-h616-operating-points";
+        nvmem-cells = <&speedbin_efuse>;
+        opp-shared;
 
-        opp-1080000000 {
+        opp-480000000 {
             clock-latency-ns = <244144>; /* 8 32k periods */
-            opp-hz = /bits/ 64 <1080000000>;
+            opp-hz = /bits/ 64 <480000000>;
 
-            opp-microvolt-speed0 = <1060000>;
-            opp-microvolt-speed1 = <880000>;
-            opp-microvolt-speed2 = <840000>;
+            opp-microvolt = <900000>;
+            opp-supported-hw = <0x1f>;
         };
 
-        opp-1320000000 {
+        opp-792000000 {
             clock-latency-ns = <244144>; /* 8 32k periods */
-            opp-hz = /bits/ 64 <1320000000>;
+            opp-hz = /bits/ 64 <792000000>;
 
-            opp-microvolt-speed0 = <1160000>;
-            opp-microvolt-speed1 = <940000>;
-            opp-microvolt-speed2 = <900000>;
+            opp-microvolt-speed1 = <900000>;
+            opp-microvolt-speed4 = <940000>;
+            opp-supported-hw = <0x12>;
         };
 
-        opp-1488000000 {
+        opp-1512000000 {
             clock-latency-ns = <244144>; /* 8 32k periods */
-            opp-hz = /bits/ 64 <1488000000>;
+            opp-hz = /bits/ 64 <1512000000>;
 
-            opp-microvolt-speed0 = <1160000>;
-            opp-microvolt-speed1 = <1000000>;
-            opp-microvolt-speed2 = <960000>;
+            opp-microvolt = <1100000>;
+            opp-supported-hw = <0x0a>;
         };
     };
 
index d476de82e5c3f487b0275d1f2d8d8b5a79a6a116..4d5a957fa232eb55d0bd71ea887eefec35b60063 100644 (file)
@@ -120,7 +120,9 @@ additionalProperties:
         slew-rate: true
         gpio-hog: true
         gpios: true
+        input: true
         input-enable: true
+        output-enable: true
         output-high: true
         output-low: true
         line-name: true
index afcdeed4e88af625ea4f0f371cc11ffdbe824859..bc813fe74faba5ae50bc81ecb2f75f9e1d8803c9 100644 (file)
@@ -52,6 +52,9 @@ properties:
       - const: main
       - const: mm
 
+  power-domains:
+    maxItems: 1
+
 required:
   - compatible
   - reg
index 65cb2e5c5eee08a0555092823edd5606cd7aa735..eb2992a447d79c4529d79a11ff0fee6f4646f647 100644 (file)
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART)
 
 maintainers:
-  - Richard Genoud <richard.genoud@gmail.com>
+  - Richard Genoud <richard.genoud@bootlin.com>
 
 properties:
   compatible:
index 0b87c266760c6ed4326bc3ee458c77987745bae1..79798c7474768a0d167f6fef8f59ba144bba01a2 100644 (file)
@@ -171,6 +171,7 @@ allOf:
           unevaluatedProperties: false
 
         pcie-phy:
+          type: object
           description:
             Documentation/devicetree/bindings/phy/rockchip-pcie-phy.txt
 
index 41a62fd2ae1ffb4f2afaa58d204797a2b15e91ec..c1fa379f5f3ea1388ed9e54ea8fef66d4645d673 100644 (file)
@@ -20,6 +20,11 @@ Optional properties:
   a GPIO spec for the external headphone detect pin. If jd-mode = 0,
   we will get the JD status by getting the value of hp-detect-gpios.
 
+- cbj-sleeve-gpios:
+  a GPIO spec to control the external combo jack circuit to tie the sleeve/ring2
+  contacts to the ground or floating. It could avoid some electric noise from the
+  active speaker jacks.
+
 - realtek,in2-differential
   Boolean. Indicate MIC2 input are differential, rather than single-ended.
 
@@ -68,6 +73,7 @@ codec: rt5650@1a {
        compatible = "realtek,rt5650";
        reg = <0x1a>;
        hp-detect-gpios = <&gpio 19 0>;
+       cbj-sleeve-gpios = <&gpio 20 0>;
        interrupt-parent = <&gpio>;
        interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
        realtek,dmic-en = "true";
index 0d0334cd51798b63af73cb86f891c07e1c7e587c..3a45a20fc05a1f90a67b5b61e6bbb654145928a3 100644 (file)
@@ -24,10 +24,10 @@ fragmentation statistics can be obtained through gfp flag information of
 each page. It is already implemented and activated if page owner is
 enabled. Other usages are more than welcome.
 
-It can also be used to show all the stacks and their outstanding
-allocations, which gives us a quick overview of where the memory is going
-without the need to screen through all the pages and match the allocation
-and free operation.
+It can also be used to show all the stacks and their current number of
+allocated base pages, which gives us a quick overview of where the memory
+is going without the need to screen through all the pages and match the
+allocation and free operation.
 
 page owner is disabled by default. So, if you'd like to use it, you need
 to add "page_owner=on" to your boot cmdline. If the kernel is built
@@ -75,42 +75,45 @@ Usage
 
        cat /sys/kernel/debug/page_owner_stacks/show_stacks > stacks.txt
        cat stacks.txt
-        prep_new_page+0xa9/0x120
-        get_page_from_freelist+0x7e6/0x2140
-        __alloc_pages+0x18a/0x370
-        new_slab+0xc8/0x580
-        ___slab_alloc+0x1f2/0xaf0
-        __slab_alloc.isra.86+0x22/0x40
-        kmem_cache_alloc+0x31b/0x350
-        __khugepaged_enter+0x39/0x100
-        dup_mmap+0x1c7/0x5ce
-        copy_process+0x1afe/0x1c90
-        kernel_clone+0x9a/0x3c0
-        __do_sys_clone+0x66/0x90
-        do_syscall_64+0x7f/0x160
-        entry_SYSCALL_64_after_hwframe+0x6c/0x74
-       stack_count: 234
+        post_alloc_hook+0x177/0x1a0
+        get_page_from_freelist+0xd01/0xd80
+        __alloc_pages+0x39e/0x7e0
+        allocate_slab+0xbc/0x3f0
+        ___slab_alloc+0x528/0x8a0
+        kmem_cache_alloc+0x224/0x3b0
+        sk_prot_alloc+0x58/0x1a0
+        sk_alloc+0x32/0x4f0
+        inet_create+0x427/0xb50
+        __sock_create+0x2e4/0x650
+        inet_ctl_sock_create+0x30/0x180
+        igmp_net_init+0xc1/0x130
+        ops_init+0x167/0x410
+        setup_net+0x304/0xa60
+        copy_net_ns+0x29b/0x4a0
+        create_new_namespaces+0x4a1/0x820
+       nr_base_pages: 16
        ...
        ...
        echo 7000 > /sys/kernel/debug/page_owner_stacks/count_threshold
        cat /sys/kernel/debug/page_owner_stacks/show_stacks> stacks_7000.txt
        cat stacks_7000.txt
-        prep_new_page+0xa9/0x120
-        get_page_from_freelist+0x7e6/0x2140
-        __alloc_pages+0x18a/0x370
-        alloc_pages_mpol+0xdf/0x1e0
-        folio_alloc+0x14/0x50
-        filemap_alloc_folio+0xb0/0x100
-        page_cache_ra_unbounded+0x97/0x180
-        filemap_fault+0x4b4/0x1200
-        __do_fault+0x2d/0x110
-        do_pte_missing+0x4b0/0xa30
-        __handle_mm_fault+0x7fa/0xb70
-        handle_mm_fault+0x125/0x300
-        do_user_addr_fault+0x3c9/0x840
-        exc_page_fault+0x68/0x150
-        asm_exc_page_fault+0x22/0x30
-       stack_count: 8248
+        post_alloc_hook+0x177/0x1a0
+        get_page_from_freelist+0xd01/0xd80
+        __alloc_pages+0x39e/0x7e0
+        alloc_pages_mpol+0x22e/0x490
+        folio_alloc+0xd5/0x110
+        filemap_alloc_folio+0x78/0x230
+        page_cache_ra_order+0x287/0x6f0
+        filemap_get_pages+0x517/0x1160
+        filemap_read+0x304/0x9f0
+        xfs_file_buffered_read+0xe6/0x1d0 [xfs]
+        xfs_file_read_iter+0x1f0/0x380 [xfs]
+        __kernel_read+0x3b9/0x730
+        kernel_read_file+0x309/0x4d0
+        __do_sys_finit_module+0x381/0x730
+        do_syscall_64+0x8d/0x150
+        entry_SYSCALL_64_after_hwframe+0x62/0x6a
+       nr_base_pages: 20824
        ...
 
        cat /sys/kernel/debug/page_owner > page_owner_full.txt
index bb2100228cc7b67236b2e2f1dfa92af609e21e02..6e9a4597bf2cbbb9ddb3d9b727c07150efa37f25 100644 (file)
@@ -252,7 +252,7 @@ an involved disclosed party. The current ambassadors list:
   AMD          Tom Lendacky <thomas.lendacky@amd.com>
   Ampere       Darren Hart <darren@os.amperecomputing.com>
   ARM          Catalin Marinas <catalin.marinas@arm.com>
-  IBM Power    Anton Blanchard <anton@linux.ibm.com>
+  IBM Power    Michael Ellerman <ellerman@au.ibm.com>
   IBM Z                Christian Borntraeger <borntraeger@de.ibm.com>
   Intel                Tony Luck <tony.luck@intel.com>
   Qualcomm     Trilok Soni <quic_tsoni@quicinc.com>
index 5c4fa9f5d1cdb7a1691c95d09180be804b2f9e55..c9137710633a37d6c88c46191dbfc7e4fc4d32c6 100644 (file)
@@ -16,7 +16,7 @@ support corresponds to ``S`` values in the ``MAINTAINERS`` file.
 Architecture   Level of support  Constraints
 =============  ================  ==============================================
 ``arm64``      Maintained        Little Endian only.
-``loongarch``  Maintained        -
+``loongarch``  Maintained        \-
 ``um``         Maintained        ``x86_64`` only.
 ``x86``        Maintained        ``x86_64`` only.
 =============  ================  ==============================================
index f8786be15183c15879a188f61fa36bceda99c6e9..7fe8ef9718d8e357567671295a3cc4dc1c97751a 100644 (file)
@@ -129,11 +129,8 @@ adaptive-tick CPUs:  At least one non-adaptive-tick CPU must remain
 online to handle timekeeping tasks in order to ensure that system
 calls like gettimeofday() returns accurate values on adaptive-tick CPUs.
 (This is not an issue for CONFIG_NO_HZ_IDLE=y because there are no running
-user processes to observe slight drifts in clock rate.)  Therefore, the
-boot CPU is prohibited from entering adaptive-ticks mode.  Specifying a
-"nohz_full=" mask that includes the boot CPU will result in a boot-time
-error message, and the boot CPU will be removed from the mask.  Note that
-this means that your system must have at least two CPUs in order for
+user processes to observe slight drifts in clock rate.) Note that this
+means that your system must have at least two CPUs in order for
 CONFIG_NO_HZ_FULL=y to do anything for you.
 
 Finally, adaptive-ticks CPUs must have their RCU callbacks offloaded.
index 7fac6f75d0782062f3f11c342068e9f13e90f2ad..fe0ff5a127f3f9255fe2606c15beb9380522cc4c 100644 (file)
@@ -7,12 +7,13 @@
 
  司延腾 Yanteng Si <siyanteng@loongson.cn>
  周彬彬 Binbin Zhou <zhoubinbin@loongson.cn>
+ 陈兴友 Xingyou Chen <rockrush@rockwork.org>
 
 .. _cn_workqueue.rst:
 
-=========================
¹¶å\8f\91管ç\90\86ç\9a\84å·¥ä½\9cé\98\9få\88\97 (cmwq)
-=========================
+========
·¥ä½\9cé\98\9få\88\97
+========
 
 :日期: September, 2010
 :作者: Tejun Heo <tj@kernel.org>
@@ -22,7 +23,7 @@
 简介
 ====
 
-在很多情况下,需要一个异步进程的执行环境,工作队列(wq)API是这种情况下
+在很多情况下,需要一个异步的程序执行环境,工作队列(wq)API是这种情况下
 最常用的机制。
 
 当需要这样一个异步执行上下文时,一个描述将要执行的函数的工作项(work,
@@ -34,8 +35,8 @@
 队列时,工作者又开始执行。
 
 
-为什么要cmwq?
-=============
+为什么要有并发管理工作队列?
+===========================
 
 在最初的wq实现中,多线程(MT)wq在每个CPU上有一个工作者线程,而单线程
 (ST)wq在全系统有一个工作者线程。一个MT wq需要保持与CPU数量相同的工
 向该函数的工作项,并在工作队列中排队等待该工作项。(就是挂到workqueue
 队列里面去)
 
-特定目的线程,称为工作线程(工作者),一个接一个地执行队列中的功能。
-如果没有工作项排队,工作者线程就会闲置。这些工作者线程被管理在所谓
-的工作者池中。
+工作项可以在线程或BH(软中断)上下文中执行。
+
+对于由线程执行的工作队列,被称为(内核)工作者([k]worker)的特殊
+线程会依次执行其中的函数。如果没有工作项排队,工作者线程就会闲置。
+这些工作者线程被管理在所谓的工作者池中。
 
 cmwq设计区分了面向用户的工作队列,子系统和驱动程序在上面排队工作,
 以及管理工作者池和处理排队工作项的后端机制。
@@ -84,6 +87,10 @@ cmwq设计区分了面向用户的工作队列,子系统和驱动程序在上
 优先级的工作项,还有一些额外的工作者池,用于服务未绑定工作队列的工
 作项目——这些后备池的数量是动态的。
 
+BH工作队列使用相同的结构。然而,由于同一时间只可能有一个执行上下文,
+不需要担心并发问题。每个CPU上的BH工作者池只包含一个用于表示BH执行
+上下文的虚拟工作者。BH工作队列可以被看作软中断的便捷接口。
+
 当他们认为合适的时候,子系统和驱动程序可以通过特殊的
 ``workqueue API`` 函数创建和排队工作项。他们可以通过在工作队列上
 设置标志来影响工作项执行方式的某些方面,他们把工作项放在那里。这些
@@ -95,9 +102,9 @@ cmwq设计区分了面向用户的工作队列,子系统和驱动程序在上
 否则一个绑定的工作队列的工作项将被排在与发起线程运行的CPU相关的普
 通或高级工作工作者池的工作项列表中。
 
-对于任何工作者池的实施,管理并发水平(有多少执行上下文处于活动状
-态)是一个重要问题。最低水平是为了节省资源,而饱和水平是指系统被
-充分使用。
+对于任何线程池的实施,管理并发水平(有多少执行上下文处于活动状
+态)是一个重要问题。cmwq试图将并发保持在一个尽可能低且充足的
+水平。最低水平是为了节省资源,而充足是为了使系统能被充分使用。
 
 每个与实际CPU绑定的worker-pool通过钩住调度器来实现并发管理。每当
 一个活动的工作者被唤醒或睡眠时,工作者池就会得到通知,并跟踪当前可
@@ -140,6 +147,17 @@ workqueue将自动创建与属性相匹配的后备工作者池。调节并发
 ``flags``
 ---------
 
+``WQ_BH``
+  BH工作队列可以被看作软中断的便捷接口。它总是每个CPU一份,
+  其中的各个工作项也会按在队列中的顺序,被所属CPU在软中断
+  上下文中执行。
+
+  BH工作队列的 ``max_active`` 值必须为0,且只能单独或和
+  ``WQ_HIGHPRI`` 标志组合使用。
+
+  BH工作项不可以睡眠。像延迟排队、冲洗、取消等所有其他特性
+  都是支持的。
+
 ``WQ_UNBOUND``
   排队到非绑定wq的工作项由特殊的工作者池提供服务,这些工作者不
   绑定在任何特定的CPU上。这使得wq表现得像一个简单的执行环境提
@@ -184,25 +202,21 @@ workqueue将自动创建与属性相匹配的后备工作者池。调节并发
 --------------
 
 ``@max_active`` 决定了每个CPU可以分配给wq的工作项的最大执行上
-下文数量。例如,如果 ``@max_active为16`` ,每个CPU最多可以同
-时执行16个wq的工作项。
+下文数量。例如,如果 ``@max_active`` 为16 ,每个CPU最多可以同
+时执行16个wq的工作项。它总是每CPU属性,即便对于未绑定 wq。
 
-目前,对于一个绑定的wq, ``@max_active`` 的最大限制是512,当指
-定为0时使用的默认值是256。对于非绑定的wq,其限制是512和
-4 * ``num_possible_cpus()`` 中的较高值。这些值被选得足够高,所
-以它们不是限制性因素,同时会在失控情况下提供保护。
+``@max_active`` 的最大限制是512,当指定为0时使用的默认值是256。
+这些值被选得足够高,所以它们不是限制性因素,同时会在失控情况下提供
+保护。
 
 一个wq的活动工作项的数量通常由wq的用户来调节,更具体地说,是由用
 户在同一时间可以排列多少个工作项来调节。除非有特定的需求来控制活动
 工作项的数量,否则建议指定 为"0"。
 
-一些用户依赖于ST wq的严格执行顺序。 ``@max_active`` 为1和 ``WQ_UNBOUND``
-的组合用来实现这种行为。这种wq上的工作项目总是被排到未绑定的工作池
-中,并且在任何时候都只有一个工作项目处于活动状态,从而实现与ST wq相
-同的排序属性。
-
-在目前的实现中,上述配置只保证了特定NUMA节点内的ST行为。相反,
-``alloc_ordered_workqueue()`` 应该被用来实现全系统的ST行为。
+一些用户依赖于任意时刻最多只有一个工作项被执行,且各工作项被按队列中
+顺序处理带来的严格执行顺序。``@max_active`` 为1和 ``WQ_UNBOUND``
+的组合曾被用来实现这种行为,现在不用了。请使用
+``alloc_ordered_workqueue()`` 。
 
 
 执行场景示例
@@ -285,7 +299,7 @@ And with cmwq with ``@max_active`` >= 3, ::
 * 除非有特殊需要,建议使用0作为@max_active。在大多数使用情
   况下,并发水平通常保持在默认限制之下。
 
-* ä¸\80个wqä½\9c为å\89\8dè¿\9bè¿\9b度ä¿\9dè¯\81ï¼\88WQ_MEM_RECLAIM,冲洗(flush)和工
+* ä¸\80个wqä½\9c为å\89\8dè¿\9bè¿\9b度ä¿\9dè¯\81ï¼\8c``WQ_MEM_RECLAIM`` ,冲洗(flush)和工
   作项属性的域。不涉及内存回收的工作项,不需要作为工作项组的一
   部分被刷新,也不需要任何特殊属性,可以使用系统中的一个wq。使
   用专用wq和系统wq在执行特性上没有区别。
@@ -294,6 +308,337 @@ And with cmwq with ``@max_active`` >= 3, ::
   益的,因为wq操作和工作项执行中的定位水平提高了。
 
 
+亲和性作用域
+============
+
+一个非绑定工作队列根据其亲和性作用域来对CPU进行分组以提高缓存
+局部性。比如如果一个工作队列使用默认的“cache”亲和性作用域,
+它将根据最后一级缓存的边界来分组处理器。这个工作队列上的工作项
+将被分配给一个与发起CPU共用最后级缓存的处理器上的工作者。根据
+``affinity_strict`` 的设置,工作者在启动后可能被允许移出
+所在作用域,也可能不被允许。
+
+工作队列目前支持以下亲和性作用域。
+
+``default``
+  使用模块参数 ``workqueue.default_affinity_scope`` 指定
+  的作用域,该参数总是会被设为以下作用域中的一个。
+
+``cpu``
+  CPU不被分组。一个CPU上发起的工作项会被同一CPU上的工作者执行。
+  这使非绑定工作队列表现得像是不含并发管理的每CPU工作队列。
+
+``smt``
+  CPU被按SMT边界分组。这通常意味着每个物理CPU核上的各逻辑CPU会
+  被分进同一组。
+
+``cache``
+  CPU被按缓存边界分组。采用哪个缓存边界由架构代码决定。很多情况
+  下会使用L3。这是默认的亲和性作用域。
+
+``numa``
+  CPU被按NUMA边界分组。
+
+``system``
+  所有CPU被放在同一组。工作队列不尝试在临近发起CPU的CPU上运行
+  工作项。
+
+默认的亲和性作用域可以被模块参数 ``workqueue.default_affinity_scope``
+修改,特定工作队列的亲和性作用域可以通过 ``apply_workqueue_attrs()``
+被更改。
+
+如果设置了 ``WQ_SYSFS`` ,工作队列会在它的 ``/sys/devices/virtual/workqueue/WQ_NAME/``
+目录中有以下亲和性作用域相关的接口文件。
+
+``affinity_scope``
+  读操作以查看当前的亲和性作用域。写操作用于更改设置。
+
+  当前作用域是默认值时,当前生效的作用域也可以被从这个文件中
+  读到(小括号内),例如 ``default (cache)`` 。
+
+``affinity_strict``
+  默认值0表明亲和性作用域不是严格的。当一个工作项开始执行时,
+  工作队列尽量尝试使工作者处于亲和性作用域内,称为遣返。启动后,
+  调度器可以自由地将工作者调度到系统中任意它认为合适的地方去。
+  这使得在保留使用其他CPU(如果必需且有可用)能力的同时,
+  还能从作用域局部性上获益。
+
+  如果设置为1,作用域内的所有工作者将被保证总是处于作用域内。
+  这在跨亲和性作用域会导致如功耗、负载隔离等方面的潜在影响时
+  会有用。严格的NUMA作用域也可用于和旧版内核中工作队列的行为
+  保持一致。
+
+
+亲和性作用域与性能
+==================
+
+如果非绑定工作队列的行为对绝大多数使用场景来说都是最优的,
+不需要更多调节,就完美了。很不幸,在当前内核中,重度使用
+工作队列时,需要在局部性和利用率间显式地作一个明显的权衡。
+
+更高的局部性带来更高效率,也就是相同数量的CPU周期内可以做
+更多工作。然而,如果发起者没能将工作项充分地分散在亲和性
+作用域间,更高的局部性也可能带来更低的整体系统利用率。以下
+dm-crypt 的性能测试清楚地阐明了这一取舍。
+
+测试运行在一个12核24线程、4个L3缓存的处理器(AMD Ryzen
+9 3900x)上。为保持一致性,关闭CPU超频。 ``/dev/dm-0``
+是NVME SSD(三星 990 PRO)上创建,用 ``cryptsetup``
+以默认配置打开的一个 dm-crypt 设备。
+
+
+场景 1: 机器上遍布着有充足的发起者和工作量
+------------------------------------------
+
+使用命令:::
+
+  $ fio --filename=/dev/dm-0 --direct=1 --rw=randrw --bs=32k --ioengine=libaio \
+    --iodepth=64 --runtime=60 --numjobs=24 --time_based --group_reporting \
+    --name=iops-test-job --verify=sha512
+
+这里有24个发起者,每个同时发起64个IO。 ``--verify=sha512``
+使得 ``fio`` 每次生成和读回内容受发起者和 ``kcryptd``
+间的执行局部性影响。下面是基于不同 ``kcryptd`` 的亲和性
+作用域设置,各经过五次测试得到的读取带宽和CPU利用率数据。
+
+.. list-table::
+   :widths: 16 20 20
+   :header-rows: 1
+
+   * - 亲和性
+     - 带宽 (MiBps)
+     - CPU利用率(%)
+
+   * - system
+     - 1159.40 ±1.34
+     - 99.31 ±0.02
+
+   * - cache
+     - 1166.40 ±0.89
+     - 99.34 ±0.01
+
+   * - cache (strict)
+     - 1166.00 ±0.71
+     - 99.35 ±0.01
+
+在系统中分布着足够多发起者的情况下,不论严格与否,“cache”
+没有表现得更差。三种配置均使整个机器达到饱和,但由于提高了
+局部性,缓存相关的两种有0.6%的(带宽)提升。
+
+
+场景 2: 更少发起者,足以达到饱和的工作量
+----------------------------------------
+
+使用命令:::
+
+  $ fio --filename=/dev/dm-0 --direct=1 --rw=randrw --bs=32k \
+    --ioengine=libaio --iodepth=64 --runtime=60 --numjobs=8 \
+    --time_based --group_reporting --name=iops-test-job --verify=sha512
+
+与上一个场景唯一的区别是 ``--numjobs=8``。 发起者数量
+减少为三分之一,但仍然有足以使系统达到饱和的工作总量。
+
+.. list-table::
+   :widths: 16 20 20
+   :header-rows: 1
+
+   * - 亲和性
+     - 带宽 (MiBps)
+     - CPU利用率(%)
+
+   * - system
+     - 1155.40 ±0.89
+     - 97.41 ±0.05
+
+   * - cache
+     - 1154.40 ±1.14
+     - 96.15 ±0.09
+
+   * - cache (strict)
+     - 1112.00 ±4.64
+     - 93.26 ±0.35
+
+这里有超过使系统达到饱和所需的工作量。“system”和“cache”
+都接近但并未使机器完全饱和。“cache”消耗更少的CPU但更高的
+效率使其得到和“system”相同的带宽。
+
+八个发起者盘桓在四个L3缓存作用域间仍然允许“cache (strict)”
+几乎使机器饱和,但缺少对工作的保持(不移到空闲处理器上)
+开始带来3.7%的带宽损失。
+
+
+场景 3: 更少发起者,不充足的工作量
+----------------------------------
+
+使用命令:::
+
+  $ fio --filename=/dev/dm-0 --direct=1 --rw=randrw --bs=32k \
+    --ioengine=libaio --iodepth=64 --runtime=60 --numjobs=4 \
+    --time_based --group_reporting --name=iops-test-job --verify=sha512
+
+再次,唯一的区别是 ``--numjobs=4``。由于发起者减少到四个,
+现在没有足以使系统饱和的工作量,带宽变得依赖于完成时延。
+
+.. list-table::
+   :widths: 16 20 20
+   :header-rows: 1
+
+   * - 亲和性
+     - 带宽 (MiBps)
+     - CPU利用率(%)
+
+   * - system
+     - 993.60 ±1.82
+     - 75.49 ±0.06
+
+   * - cache
+     - 973.40 ±1.52
+     - 74.90 ±0.07
+
+   * - cache (strict)
+     - 828.20 ±4.49
+     - 66.84 ±0.29
+
+现在,局部性和利用率间的权衡更清晰了。“cache”展示出相比
+“system”2%的带宽损失,而“cache (strict)”跌到20%。
+
+
+结论和建议
+----------
+
+在以上试验中,虽然一致并且也明显,但“cache”亲和性作用域
+相比“system”的性能优势并不大。然而,这影响是依赖于作用域
+间距离的,在更复杂的处理器拓扑下可能有更明显的影响。
+
+虽然这些情形下缺少工作保持是有坏处的,但比“cache (strict)”
+好多了,而且最大化工作队列利用率的需求也并不常见。因此,
+“cache”是非绑定池的默认亲和性作用域。
+
+* 由于不存在一个适用于大多数场景的选择,对于可能需要消耗
+  大量CPU的工作队列,建议通过 ``apply_workqueue_attrs()``
+  进行(专门)配置,并考虑是否启用 ``WQ_SYSFS``。
+
+* 设置了严格“cpu”亲和性作用域的非绑定工作队列,它的行为与
+  ``WQ_CPU_INTENSIVE`` 每CPU工作队列一样。后者没有真正
+  优势,而前者提供了大幅度的灵活性。
+
+* 亲和性作用域是从Linux v6.5起引入的。为了模拟旧版行为,
+  可以使用严格的“numa”亲和性作用域。
+
+* 不严格的亲和性作用域中,缺少工作保持大概缘于调度器。内核
+  为什么没能维护好大多数场景下的工作保持,把事情作对,还没有
+  理论上的解释。因此,未来调度器的改进可能会使我们不再需要
+  这些调节项。
+
+
+检查配置
+========
+
+使用 tools/workqueue/wq_dump.py(drgn脚本) 来检查未
+绑定CPU的亲和性配置,工作者池,以及工作队列如何映射到池上: ::
+
+  $ tools/workqueue/wq_dump.py
+  Affinity Scopes
+  ===============
+  wq_unbound_cpumask=0000000f
+
+  CPU
+    nr_pods  4
+    pod_cpus [0]=00000001 [1]=00000002 [2]=00000004 [3]=00000008
+    pod_node [0]=0 [1]=0 [2]=1 [3]=1
+    cpu_pod  [0]=0 [1]=1 [2]=2 [3]=3
+
+  SMT
+    nr_pods  4
+    pod_cpus [0]=00000001 [1]=00000002 [2]=00000004 [3]=00000008
+    pod_node [0]=0 [1]=0 [2]=1 [3]=1
+    cpu_pod  [0]=0 [1]=1 [2]=2 [3]=3
+
+  CACHE (default)
+    nr_pods  2
+    pod_cpus [0]=00000003 [1]=0000000c
+    pod_node [0]=0 [1]=1
+    cpu_pod  [0]=0 [1]=0 [2]=1 [3]=1
+
+  NUMA
+    nr_pods  2
+    pod_cpus [0]=00000003 [1]=0000000c
+    pod_node [0]=0 [1]=1
+    cpu_pod  [0]=0 [1]=0 [2]=1 [3]=1
+
+  SYSTEM
+    nr_pods  1
+    pod_cpus [0]=0000000f
+    pod_node [0]=-1
+    cpu_pod  [0]=0 [1]=0 [2]=0 [3]=0
+
+  Worker Pools
+  ============
+  pool[00] ref= 1 nice=  0 idle/workers=  4/  4 cpu=  0
+  pool[01] ref= 1 nice=-20 idle/workers=  2/  2 cpu=  0
+  pool[02] ref= 1 nice=  0 idle/workers=  4/  4 cpu=  1
+  pool[03] ref= 1 nice=-20 idle/workers=  2/  2 cpu=  1
+  pool[04] ref= 1 nice=  0 idle/workers=  4/  4 cpu=  2
+  pool[05] ref= 1 nice=-20 idle/workers=  2/  2 cpu=  2
+  pool[06] ref= 1 nice=  0 idle/workers=  3/  3 cpu=  3
+  pool[07] ref= 1 nice=-20 idle/workers=  2/  2 cpu=  3
+  pool[08] ref=42 nice=  0 idle/workers=  6/  6 cpus=0000000f
+  pool[09] ref=28 nice=  0 idle/workers=  3/  3 cpus=00000003
+  pool[10] ref=28 nice=  0 idle/workers= 17/ 17 cpus=0000000c
+  pool[11] ref= 1 nice=-20 idle/workers=  1/  1 cpus=0000000f
+  pool[12] ref= 2 nice=-20 idle/workers=  1/  1 cpus=00000003
+  pool[13] ref= 2 nice=-20 idle/workers=  1/  1 cpus=0000000c
+
+  Workqueue CPU -> pool
+  =====================
+  [    workqueue \ CPU              0  1  2  3 dfl]
+  events                   percpu   0  2  4  6
+  events_highpri           percpu   1  3  5  7
+  events_long              percpu   0  2  4  6
+  events_unbound           unbound  9  9 10 10  8
+  events_freezable         percpu   0  2  4  6
+  events_power_efficient   percpu   0  2  4  6
+  events_freezable_power_  percpu   0  2  4  6
+  rcu_gp                   percpu   0  2  4  6
+  rcu_par_gp               percpu   0  2  4  6
+  slub_flushwq             percpu   0  2  4  6
+  netns                    ordered  8  8  8  8  8
+  ...
+
+参见命令的帮助消息以获取更多信息。
+
+
+监视
+====
+
+使用 tools/workqueue/wq_monitor.py 来监视工作队列的运行: ::
+
+  $ tools/workqueue/wq_monitor.py events
+                              total  infl  CPUtime  CPUhog CMW/RPR  mayday rescued
+  events                      18545     0      6.1       0       5       -       -
+  events_highpri                  8     0      0.0       0       0       -       -
+  events_long                     3     0      0.0       0       0       -       -
+  events_unbound              38306     0      0.1       -       7       -       -
+  events_freezable                0     0      0.0       0       0       -       -
+  events_power_efficient      29598     0      0.2       0       0       -       -
+  events_freezable_power_        10     0      0.0       0       0       -       -
+  sock_diag_events                0     0      0.0       0       0       -       -
+
+                              total  infl  CPUtime  CPUhog CMW/RPR  mayday rescued
+  events                      18548     0      6.1       0       5       -       -
+  events_highpri                  8     0      0.0       0       0       -       -
+  events_long                     3     0      0.0       0       0       -       -
+  events_unbound              38322     0      0.1       -       7       -       -
+  events_freezable                0     0      0.0       0       0       -       -
+  events_power_efficient      29603     0      0.2       0       0       -       -
+  events_freezable_power_        10     0      0.0       0       0       -       -
+  sock_diag_events                0     0      0.0       0       0       -       -
+
+  ...
+
+参见命令的帮助消息以获取更多信息。
+
+
 调试
 ====
 
@@ -330,7 +675,6 @@ And with cmwq with ``@max_active`` >= 3, ::
 
 工作队列保证,如果在工作项排队后满足以下条件,则工作项不能重入:
 
-
         1. 工作函数没有被改变。
         2. 没有人将该工作项排到另一个工作队列中。
         3. 该工作项尚未被重新启动。
index c23fda1aa1f092302910e962e7ce8c107030a3ca..75a7564354f64ca1fa1c95db6dc0eed8737f7fb4 100644 (file)
@@ -553,7 +553,7 @@ F:  Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml
 F:     drivers/input/misc/adxl34x.c
 
 ADXL355 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
-M:     Puranjay Mohan <puranjay12@gmail.com>
+M:     Puranjay Mohan <puranjay@kernel.org>
 L:     linux-iio@vger.kernel.org
 S:     Supported
 F:     Documentation/devicetree/bindings/iio/accel/adi,adxl355.yaml
@@ -1062,6 +1062,9 @@ F:        drivers/gpu/drm/amd/pm/
 
 AMD PSTATE DRIVER
 M:     Huang Rui <ray.huang@amd.com>
+M:     Gautham R. Shenoy <gautham.shenoy@amd.com>
+M:     Mario Limonciello <mario.limonciello@amd.com>
+R:     Perry Yuan <perry.yuan@amd.com>
 L:     linux-pm@vger.kernel.org
 S:     Supported
 F:     Documentation/admin-guide/pm/amd-pstate.rst
@@ -3714,7 +3717,7 @@ F:        drivers/iio/imu/bmi323/
 
 BPF JIT for ARM
 M:     Russell King <linux@armlinux.org.uk>
-M:     Puranjay Mohan <puranjay12@gmail.com>
+M:     Puranjay Mohan <puranjay@kernel.org>
 L:     bpf@vger.kernel.org
 S:     Maintained
 F:     arch/arm/net/
@@ -3764,6 +3767,8 @@ X:        arch/riscv/net/bpf_jit_comp64.c
 
 BPF JIT for RISC-V (64-bit)
 M:     Björn Töpel <bjorn@kernel.org>
+R:     Pu Lehui <pulehui@huawei.com>
+R:     Puranjay Mohan <puranjay@kernel.org>
 L:     bpf@vger.kernel.org
 S:     Maintained
 F:     arch/riscv/net/
@@ -4191,7 +4196,6 @@ S:        Supported
 F:     drivers/scsi/bnx2i/
 
 BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
-M:     Ariel Elior <aelior@marvell.com>
 M:     Sudarsana Kalluru <skalluru@marvell.com>
 M:     Manish Chopra <manishc@marvell.com>
 L:     netdev@vger.kernel.org
@@ -7829,9 +7833,8 @@ W:        http://aeschi.ch.eu.org/efs/
 F:     fs/efs/
 
 EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER
-M:     Douglas Miller <dougmill@linux.ibm.com>
 L:     netdev@vger.kernel.org
-S:     Maintained
+S:     Orphan
 F:     drivers/net/ethernet/ibm/ehea/
 
 ELM327 CAN NETWORK DRIVER
@@ -8746,10 +8749,9 @@ S:       Orphan
 F:     drivers/usb/gadget/udc/fsl*
 
 FREESCALE USB PHY DRIVER
-M:     Ran Wang <ran.wang_1@nxp.com>
 L:     linux-usb@vger.kernel.org
 L:     linuxppc-dev@lists.ozlabs.org
-S:     Maintained
+S:     Orphan
 F:     drivers/usb/phy/phy-fsl-usb*
 
 FREEVXFS FILESYSTEM
@@ -9577,7 +9579,7 @@ F:        kernel/power/
 
 HID CORE LAYER
 M:     Jiri Kosina <jikos@kernel.org>
-M:     Benjamin Tissoires <benjamin.tissoires@redhat.com>
+M:     Benjamin Tissoires <bentiss@kernel.org>
 L:     linux-input@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git
@@ -10024,7 +10026,7 @@ F:      drivers/media/platform/st/sti/hva
 
 HWPOISON MEMORY FAILURE HANDLING
 M:     Miaohe Lin <linmiaohe@huawei.com>
-R:     Naoya Horiguchi <naoya.horiguchi@nec.com>
+R:     Naoya Horiguchi <nao.horiguchi@gmail.com>
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     mm/hwpoison-inject.c
@@ -11995,7 +11997,7 @@ F:      include/keys/encrypted-type.h
 F:     security/keys/encrypted-keys/
 
 KEYS-TRUSTED
-M:     James Bottomley <jejb@linux.ibm.com>
+M:     James Bottomley <James.Bottomley@HansenPartnership.com>
 M:     Jarkko Sakkinen <jarkko@kernel.org>
 M:     Mimi Zohar <zohar@linux.ibm.com>
 L:     linux-integrity@vger.kernel.org
@@ -14357,7 +14359,7 @@ F:      drivers/dma/at_xdmac.c
 F:     include/dt-bindings/dma/at91.h
 
 MICROCHIP AT91 SERIAL DRIVER
-M:     Richard Genoud <richard.genoud@gmail.com>
+M:     Richard Genoud <richard.genoud@bootlin.com>
 S:     Maintained
 F:     Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml
 F:     drivers/tty/serial/atmel_serial.c
@@ -15162,9 +15164,8 @@ F:      drivers/scsi/myrb.*
 F:     drivers/scsi/myrs.*
 
 MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
-M:     Chris Lee <christopher.lee@cspi.com>
 L:     netdev@vger.kernel.org
-S:     Supported
+S:     Orphan
 W:     https://www.cspi.com/ethernet-products/support/downloads/
 F:     drivers/net/ethernet/myricom/myri10ge/
 
@@ -16800,12 +16801,6 @@ S:     Maintained
 F:     drivers/leds/leds-pca9532.c
 F:     include/linux/leds-pca9532.h
 
-PCA9541 I2C BUS MASTER SELECTOR DRIVER
-M:     Guenter Roeck <linux@roeck-us.net>
-L:     linux-i2c@vger.kernel.org
-S:     Maintained
-F:     drivers/i2c/muxes/i2c-mux-pca9541.c
-
 PCI DRIVER FOR AARDVARK (Marvell Armada 3700)
 M:     Thomas Petazzoni <thomas.petazzoni@bootlin.com>
 M:     Pali Rohár <pali@kernel.org>
@@ -17874,7 +17869,7 @@ F:      Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.yaml
 F:     drivers/media/rc/pwm-ir-tx.c
 
 PWM SUBSYSTEM
-M:     Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+M:     Uwe Kleine-König <ukleinek@kernel.org>
 L:     linux-pwm@vger.kernel.org
 S:     Maintained
 Q:     https://patchwork.ozlabs.org/project/linux-pwm/list/
@@ -17998,7 +17993,6 @@ S:      Supported
 F:     drivers/scsi/qedi/
 
 QLOGIC QL4xxx ETHERNET DRIVER
-M:     Ariel Elior <aelior@marvell.com>
 M:     Manish Chopra <manishc@marvell.com>
 L:     netdev@vger.kernel.org
 S:     Supported
@@ -18008,7 +18002,6 @@ F:      include/linux/qed/
 
 QLOGIC QL4xxx RDMA DRIVER
 M:     Michal Kalderon <mkalderon@marvell.com>
-M:     Ariel Elior <aelior@marvell.com>
 L:     linux-rdma@vger.kernel.org
 S:     Supported
 F:     drivers/infiniband/hw/qedr/
@@ -19669,7 +19662,7 @@ F:      drivers/scsi/sg.c
 F:     include/scsi/sg.h
 
 SCSI SUBSYSTEM
-M:     "James E.J. Bottomley" <jejb@linux.ibm.com>
+M:     "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
 M:     "Martin K. Petersen" <martin.petersen@oracle.com>
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
@@ -20178,7 +20171,6 @@ F:      include/linux/platform_data/simplefb.h
 
 SIOX
 M:     Thorsten Scherer <t.scherer@eckelmann.de>
-M:     Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 R:     Pengutronix Kernel Team <kernel@pengutronix.de>
 S:     Supported
 F:     drivers/gpio/gpio-siox.c
@@ -21927,7 +21919,7 @@ F:      include/linux/soc/ti/ti_sci_inta_msi.h
 F:     include/linux/soc/ti/ti_sci_protocol.h
 
 TEXAS INSTRUMENTS' TMP117 TEMPERATURE SENSOR DRIVER
-M:     Puranjay Mohan <puranjay12@gmail.com>
+M:     Puranjay Mohan <puranjay@kernel.org>
 L:     linux-iio@vger.kernel.org
 S:     Supported
 F:     Documentation/devicetree/bindings/iio/temperature/ti,tmp117.yaml
@@ -22840,7 +22832,7 @@ F:      drivers/usb/host/ehci*
 
 USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...)
 M:     Jiri Kosina <jikos@kernel.org>
-M:     Benjamin Tissoires <benjamin.tissoires@redhat.com>
+M:     Benjamin Tissoires <bentiss@kernel.org>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git
@@ -24468,6 +24460,14 @@ T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/har
 F:     Documentation/admin-guide/LSM/Yama.rst
 F:     security/yama/
 
+YAML NETLINK (YNL)
+M:     Donald Hunter <donald.hunter@gmail.com>
+M:     Jakub Kicinski <kuba@kernel.org>
+F:     Documentation/netlink/
+F:     Documentation/userspace-api/netlink/intro-specs.rst
+F:     Documentation/userspace-api/netlink/specs.rst
+F:     tools/net/ynl/
+
 YEALINK PHONE DRIVER
 M:     Henk Vergonet <Henk.Vergonet@gmail.com>
 L:     usbb2k-api-dev@nongnu.org
index 59d8a7f95d0a863e4308853f9e01baa9fb8fed84..d51d411d44a82e1d7dfe0566c0f2d0af3128b145 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 9
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc7
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
index 65afb1de48b36e843bd665a91df6b33badfd23d1..30f7930275d8388d6fca8ddcd97fbd56ec007873 100644 (file)
@@ -9,6 +9,14 @@
 #
 source "arch/$(SRCARCH)/Kconfig"
 
+config ARCH_CONFIGURES_CPU_MITIGATIONS
+       bool
+
+if !ARCH_CONFIGURES_CPU_MITIGATIONS
+config CPU_MITIGATIONS
+       def_bool y
+endif
+
 menu "General architecture-dependent options"
 
 config ARCH_HAS_SUBPAGE_FAULTS
index 99d2845f3feb954d495253e938fb4dec73be1720..4092bec198beca44d6c019643db6829293f7320d 100644 (file)
@@ -6,7 +6,6 @@
 config ARC
        def_bool y
        select ARC_TIMERS
-       select ARCH_HAS_CPU_CACHE_ALIASING
        select ARCH_HAS_CACHE_LINE_SIZE
        select ARCH_HAS_DEBUG_VM_PGTABLE
        select ARCH_HAS_DMA_PREP_COHERENT
index 5648748c285f52c46a5fbe8df1d5c8e683cafc88..5a8550124b73ec0ae01461af4623009110b3007e 100644 (file)
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0
 
-# uImage build relies on mkimage being availble on your host for ARC target
+# uImage build relies on mkimage being available on your host for ARC target
 # You will need to build u-boot for ARC, rename mkimage to arc-elf32-mkimage
-# and make sure it's reacable from your PATH
+# and make sure it's reachable from your PATH
 
 OBJCOPYFLAGS= -O binary -R .note -R .note.gnu.build-id -R .comment -S
 
index 3434c8131ecd546911bdbfb03d280d9b158e5a86..c0a812674ce9edac177c5ae98889766b5e052ad6 100644 (file)
        /*
         * The DW APB ICTL intc on MB is connected to CPU intc via a
         * DT "invisible" DW APB GPIO block, configured to simply pass thru
-        * interrupts - setup accordinly in platform init (plat-axs10x/ax10x.c)
+        * interrupts - setup accordingly in platform init (plat-axs10x/ax10x.c)
         *
-        * So here we mimic a direct connection betwen them, ignoring the
+        * So here we mimic a direct connection between them, ignoring the
         * ABPG GPIO. Thus set "interrupts = <24>" (DW APB GPIO to core)
         * instead of "interrupts = <12>" (DW APB ICTL to DW APB GPIO)
         *
index 6691f42550778853f2917a2d18347fd4c05f0488..41b980df862b14aa2a97867d05051f0f29434b65 100644 (file)
                };
 
                gmac: ethernet@8000 {
-                       #interrupt-cells = <1>;
                        compatible = "snps,dwmac";
                        reg = <0x8000 0x2000>;
                        interrupts = <10>;
index 90a412026e6433cb3e07d97c64e4aec879ef2c20..0e0e2d337bf8711d63f182b7f5a4a60341822d1b 100644 (file)
        /*
         * Embedded Vision subsystem UIO mappings; only relevant for EV VDK
         *
-        * This node is intentionally put outside of MB above becase
+        * This node is intentionally put outside of MB above because
         * it maps areas outside of MB's 0xez-0xfz.
         */
        uio_ev: uio@d0000000 {
diff --git a/arch/arc/include/asm/cachetype.h b/arch/arc/include/asm/cachetype.h
deleted file mode 100644 (file)
index 05fc7ed..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_ARC_CACHETYPE_H
-#define __ASM_ARC_CACHETYPE_H
-
-#include <linux/types.h>
-
-#define cpu_dcache_is_aliasing()       true
-
-#endif
index 202c78e567045bdc442c62f4a23c5b382a6d5b80..f496dbc4640b2461a7ca7696c21a19dcb6d2d6be 100644 (file)
@@ -12,7 +12,7 @@
 /*
  * DSP-related saved registers - need to be saved only when you are
  * scheduled out.
- * structure fields name must correspond to aux register defenitions for
+ * structure fields name must correspond to aux register definitions for
  * automatic offset calculation in DSP_AUX_SAVE_RESTORE macros
  */
 struct dsp_callee_regs {
index 92c3e9f13252193a1f0d241c272ee1acb6af41b6..00946fe04c9b26802aed8e214337e582476b9f5b 100644 (file)
@@ -7,7 +7,7 @@
  *  Stack switching code can no longer reliably rely on the fact that
  *  if we are NOT in user mode, stack is switched to kernel mode.
  *  e.g. L2 IRQ interrupted a L1 ISR which had not yet completed
- *  it's prologue including stack switching from user mode
+ *  its prologue including stack switching from user mode
  *
  * Vineetg: Aug 28th 2008: Bug #94984
  *  -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
         * 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode)
         * 3. But before it could switch SP from USER to KERNEL stack
         *      a L2 IRQ "Interrupts" L1
-        * Thay way although L2 IRQ happened in Kernel mode, stack is still
+        * That way although L2 IRQ happened in Kernel mode, stack is still
         * not switched.
         * To handle this, we may need to switch stack even if in kernel mode
         * provided SP has values in range of USER mode stack ( < 0x7000_0000 )
 
        GET_CURR_TASK_ON_CPU   r9
 
-       /* With current tsk in r9, get it's kernel mode stack base */
+       /* With current tsk in r9, get its kernel mode stack base */
        GET_TSK_STACK_BASE  r9, r9
 
        /* save U mode SP @ pt_regs->sp */
  * NOTE:
  *
  * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
- * for memory load operations. If used in that way interrupts are deffered
+ * for memory load operations. If used in that way interrupts are deferred
  * by hardware and that is not good.
  *-------------------------------------------------------------*/
 .macro EXCEPTION_EPILOGUE
  * NOTE:
  *
  * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
- * for memory load operations. If used in that way interrupts are deffered
+ * for memory load operations. If used in that way interrupts are deferred
  * by hardware and that is not good.
  *-------------------------------------------------------------*/
 .macro INTERRUPT_EPILOGUE  LVL
index cf1ba376e992c600b0e270056eabf9179cbd96b7..38c35722cebf0312899bf8ac63562550a779dd4e 100644 (file)
@@ -7,7 +7,7 @@
 #ifndef __ASM_ARC_ENTRY_H
 #define __ASM_ARC_ENTRY_H
 
-#include <asm/unistd.h>                /* For NR_syscalls defination */
+#include <asm/unistd.h>                /* For NR_syscalls definition */
 #include <asm/arcregs.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>     /* For VMALLOC_START */
@@ -56,7 +56,7 @@
 .endm
 
 /*-------------------------------------------------------------
- * given a tsk struct, get to the base of it's kernel mode stack
+ * given a tsk struct, get to the base of its kernel mode stack
  * tsk->thread_info is really a PAGE, whose bottom hoists stack
  * which grows upwards towards thread_info
  *------------------------------------------------------------*/
index c574712ad86589eb858c4d6b0c4c3721af3e904d..9cd79263acba824ff4e50ba5d71144bea4307b2f 100644 (file)
@@ -10,7 +10,7 @@
  * ARCv2 can support 240 interrupts in the core interrupts controllers and
  * 128 interrupts in IDU. Thus 512 virtual IRQs must be enough for most
  * configurations of boards.
- * This doesnt affect ARCompact, but we change it to same value
+ * This doesn't affect ARCompact, but we change it to same value
  */
 #define NR_IRQS                512
 
index 0d63e568d64cb524b907d80023d56c43e2bcc499..936a2f21f315ed881ff9a972ac8e68d6d93170e2 100644 (file)
@@ -46,7 +46,7 @@
  * IRQ Control Macros
  *
  * All of them have "memory" clobber (compiler barrier) which is needed to
- * ensure that LD/ST requiring irq safetly (R-M-W when LLSC is not available)
+ * ensure that LD/ST requiring irq safety (R-M-W when LLSC is not available)
  * are redone after IRQs are re-enabled (and gcc doesn't reuse stale register)
  *
  * Noted at the time of Abilis Timer List corruption
index dda471f5f05bbf06c2949daa503c272206ad0c4b..9963bb1a5733fb690476841f770318c0356056a8 100644 (file)
@@ -165,7 +165,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
  * for retiring-mm. However destroy_context( ) still needs to do that because
  * between mm_release( ) = >deactive_mm( ) and
  * mmput => .. => __mmdrop( ) => destroy_context( )
- * there is a good chance that task gets sched-out/in, making it's ASID valid
+ * there is a good chance that task gets sched-out/in, making its ASID valid
  * again (this teased me for a whole day).
  */
 
index f3eea3f30b2e2998ca9b90ae5232c47bc0837182..8ebec1b21d246e61aa688c152dba9b5e2e564104 100644 (file)
@@ -66,7 +66,7 @@
  * Other rules which cause the divergence from 1:1 mapping
  *
  *  1. Although ARC700 can do exclusive execute/write protection (meaning R
- *     can be tracked independet of X/W unlike some other CPUs), still to
+ *     can be tracked independently of X/W unlike some other CPUs), still to
  *     keep things consistent with other archs:
  *      -Write implies Read:   W => R
  *      -Execute implies Read: X => R
index 00b9318e551e7e31fc2eeff345d6d722f4e3efb6..cf79df0b257053494fcc20ba48c6105828bd4318 100644 (file)
@@ -169,7 +169,7 @@ static inline unsigned long regs_get_register(struct pt_regs *regs,
        return *(unsigned long *)((unsigned long)regs + offset);
 }
 
-extern int syscall_trace_entry(struct pt_regs *);
+extern int syscall_trace_enter(struct pt_regs *);
 extern void syscall_trace_exit(struct pt_regs *);
 
 #endif /* !__ASSEMBLY__ */
index 8b0251464ffd42b848ad61fe0e5a14b493c9389b..719112af0f41ae45ce4687d4af06bd7f0955812f 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __ARC_ASM_SHMPARAM_H
 #define __ARC_ASM_SHMPARAM_H
 
-/* Handle upto 2 cache bins */
+/* Handle up to 2 cache bins */
 #define        SHMLBA  (2 * PAGE_SIZE)
 
 /* Enforce SHMLBA in shmat */
index e0913f52c2cddadf7840282bf43fb430dba7a235..990f834909f088d8c5e57366a5c4d3ad56d800f7 100644 (file)
@@ -77,7 +77,7 @@ static inline const char *arc_platform_smp_cpuinfo(void)
 
 /*
  * ARC700 doesn't support atomic Read-Modify-Write ops.
- * Originally Interrupts had to be disabled around code to gaurantee atomicity.
+ * Originally Interrupts had to be disabled around code to guarantee atomicity.
  * The LLOCK/SCOND insns allow writing interrupt-hassle-free based atomic ops
  * based on retry-if-irq-in-atomic (with hardware assist).
  * However despite these, we provide the IRQ disabling variant
@@ -86,7 +86,7 @@ static inline const char *arc_platform_smp_cpuinfo(void)
  *     support needed.
  *
  * (2) In a SMP setup, the LLOCK/SCOND atomicity across CPUs needs to be
- *     gaurantted by the platform (not something which core handles).
+ *     guaranteed by the platform (not something which core handles).
  *     Assuming a platform won't, SMP Linux needs to use spinlocks + local IRQ
  *     disabling for atomicity.
  *
index 4c530cf131f339c5dbe92ecfce6a4f0f57a17903..12daaf3a61eaf613dcbb259643107558092db1c2 100644 (file)
@@ -38,7 +38,7 @@
 struct thread_info {
        unsigned long flags;            /* low level flags */
        unsigned long ksp;              /* kernel mode stack top in __switch_to */
-       int preempt_count;              /* 0 => preemptable, <0 => BUG */
+       int preempt_count;              /* 0 => preemptible, <0 => BUG */
        int cpu;                        /* current CPU */
        unsigned long thr_ptr;          /* TLS ptr */
        struct task_struct *task;       /* main task structure */
index 02109cd48ee1298b8a2d6da2eda5611b0d7d9643..8d1f1ef44ba75078cdd5339dd6dff7cb2825e3c6 100644 (file)
@@ -62,7 +62,7 @@
  * 8051fdc4:   st     r2,[r1,20]       ; Mem op : save result back to mem
  *
  * Joern suggested a better "C" algorithm which is great since
- * (1) It is portable to any architecure
+ * (1) It is portable to any architecture
  * (2) At the same time it takes advantage of ARC ISA (rotate intrns)
  */
 
index 2e49c81c8086b11de360c0e37421b2f9091a9c85..e238b5fd3c8cffe8da4b6e42255663b5e0aeb52a 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
  */
 
-#include <linux/linkage.h>   /* ARC_{EXTRY,EXIT} */
+#include <linux/linkage.h>   /* ARC_{ENTRY,EXIT} */
 #include <asm/entry.h>       /* SAVE_ALL_{INT1,INT2,TRAP...} */
 #include <asm/errno.h>
 #include <asm/arcregs.h>
@@ -31,7 +31,7 @@ VECTOR        res_service             ; Reset Vector
 VECTOR mem_service             ; Mem exception
 VECTOR instr_service           ; Instrn Error
 VECTOR EV_MachineCheck         ; Fatal Machine check
-VECTOR EV_TLBMissI             ; Intruction TLB miss
+VECTOR EV_TLBMissI             ; Instruction TLB miss
 VECTOR EV_TLBMissD             ; Data TLB miss
 VECTOR EV_TLBProtV             ; Protection Violation
 VECTOR EV_PrivilegeV           ; Privilege Violation
@@ -76,11 +76,11 @@ ENTRY(handle_interrupt)
        # query in hard ISR path would return false (since .IE is set) which would
        # trips genirq interrupt handling asserts.
        #
-       # So do a "soft" disable of interrutps here.
+       # So do a "soft" disable of interrupts here.
        #
        # Note this disable is only for consistent book-keeping as further interrupts
        # will be disabled anyways even w/o this. Hardware tracks active interrupts
-       # seperately in AUX_IRQ_ACT.active and will not take new interrupts
+       # separately in AUX_IRQ_ACT.active and will not take new interrupts
        # unless this one returns (or higher prio becomes pending in 2-prio scheme)
 
        IRQ_DISABLE
index 089f6680518f82908664a6f2883ab6d3e1b2c5ca..3c7e74aba6794e8c1be2c99a7aa3dbe0393e1a1a 100644 (file)
@@ -95,7 +95,7 @@ ENTRY(EV_MachineCheck)
        lr  r0, [efa]
        mov r1, sp
 
-       ; MC excpetions disable MMU
+       ; MC exceptions disable MMU
        ARC_MMU_REENABLE r3
 
        lsr     r3, r10, 8
@@ -209,7 +209,7 @@ trap_with_param:
 
 ; ---------------------------------------------
 ; syscall TRAP
-; ABI: (r0-r7) upto 8 args, (r8) syscall number
+; ABI: (r0-r7) up to 8 args, (r8) syscall number
 ; ---------------------------------------------
 
 ENTRY(EV_Trap)
index 9152782444b55737ad04a227598fc4a17f69d7a8..8d541f53fae3ecee633ce19b7f99a818d1609bd0 100644 (file)
@@ -165,7 +165,7 @@ ENTRY(first_lines_of_secondary)
        ; setup stack (fp, sp)
        mov     fp, 0
 
-       ; set it's stack base to tsk->thread_info bottom
+       ; set its stack base to tsk->thread_info bottom
        GET_TSK_STACK_BASE r0, sp
 
        j       start_kernel_secondary
index 678898757e4739da5fcffb1df8ae289a783957c2..f324f0e3341a3939ad52f44d454eebc4288500fc 100644 (file)
@@ -56,7 +56,7 @@ void arc_init_IRQ(void)
        WRITE_AUX(AUX_IRQ_CTRL, ictrl);
 
        /*
-        * ARCv2 core intc provides multiple interrupt priorities (upto 16).
+        * ARCv2 core intc provides multiple interrupt priorities (up to 16).
         * Typical builds though have only two levels (0-high, 1-low)
         * Linux by default uses lower prio 1 for most irqs, reserving 0 for
         * NMI style interrupts in future (say perf)
index e71d64119d71acc999869c56b6459d381629aadc..f8e2960832d943282a7bc698e1e229ed7a92b074 100644 (file)
@@ -190,7 +190,8 @@ static void __kprobes setup_singlestep(struct kprobe *p, struct pt_regs *regs)
        }
 }
 
-int __kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs)
+static int
+__kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs)
 {
        struct kprobe *p;
        struct kprobe_ctlblk *kcb;
@@ -241,8 +242,8 @@ int __kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs)
        return 0;
 }
 
-static int __kprobes arc_post_kprobe_handler(unsigned long addr,
-                                        struct pt_regs *regs)
+static int
+__kprobes arc_post_kprobe_handler(unsigned long addr, struct pt_regs *regs)
 {
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
index adff957962da88382f9e55e72d39eca5c5ed9dcf..6e5a651cd75cf5403001dc73c13717d0b53ffe13 100644 (file)
@@ -38,7 +38,7 @@
  * (based on a specific RTL build)
  * Below is the static map between perf generic/arc specific event_id and
  * h/w condition names.
- * At the time of probe, we loop thru each index and find it's name to
+ * At the time of probe, we loop thru each index and find its name to
  * complete the mapping of perf event_id to h/w index as latter is needed
  * to program the counter really
  */
index d08a5092c2b4d451e50b1b26e47926d04f01d2c2..7b6a9beba9db6d1dc55bae6e71c7e7c99508145d 100644 (file)
@@ -390,7 +390,7 @@ static void arc_chk_core_config(struct cpuinfo_arc *info)
 #ifdef CONFIG_ARC_HAS_DCCM
        /*
         * DCCM can be arbit placed in hardware.
-        * Make sure it's placement/sz matches what Linux is built with
+        * Make sure its placement/sz matches what Linux is built with
         */
        if ((unsigned int)__arc_dccm_base != info->dccm.base)
                panic("Linux built with incorrect DCCM Base address\n");
index 8f6f4a5429646fc431f94f5ea600caa4fa8d8d43..fefa705a8638503c596543af3cbb6ce2436586b1 100644 (file)
@@ -8,15 +8,16 @@
  *
  * vineetg: Nov 2009 (Everything needed for TIF_RESTORE_SIGMASK)
  *  -do_signal() supports TIF_RESTORE_SIGMASK
- *  -do_signal() no loner needs oldset, required by OLD sys_sigsuspend
- *  -sys_rt_sigsuspend() now comes from generic code, so discard arch implemen
+ *  -do_signal() no longer needs oldset, required by OLD sys_sigsuspend
+ *  -sys_rt_sigsuspend() now comes from generic code, so discard arch
+ *   implementation
  *  -sys_sigsuspend() no longer needs to fudge ptregs, hence that arg removed
  *  -sys_sigsuspend() no longer loops for do_signal(), sets TIF_xxx and leaves
  *   the job to do_signal()
  *
  * vineetg: July 2009
  *  -Modified Code to support the uClibc provided userland sigreturn stub
- *   to avoid kernel synthesing it on user stack at runtime, costing TLB
+ *   to avoid kernel synthesizing it on user stack at runtime, costing TLB
  *   probes and Cache line flushes.
  *
  * vineetg: July 2009
index 9b9570b79362ee08931044931bccbd965526c786..a19751e824fb4c272e5cfa21ab3349210d30bfa7 100644 (file)
@@ -89,7 +89,7 @@ int do_misaligned_access(unsigned long address, struct pt_regs *regs,
 
 /*
  * Entry point for miscll errors such as Nested Exceptions
- *  -Duplicate TLB entry is handled seperately though
+ *  -Duplicate TLB entry is handled separately though
  */
 void do_machine_check_fault(unsigned long address, struct pt_regs *regs)
 {
index 549c3f407918693f4407e4b0854cdd63d2017952..61a1b2b96e1d81396d6b7f7ab505756d0d8bb86e 100644 (file)
@@ -41,8 +41,8 @@ SECTIONS
 #endif
 
        /*
-        * The reason for having a seperate subsection .init.ramfs is to
-        * prevent objump from including it in kernel dumps
+        * The reason for having a separate subsection .init.ramfs is to
+        * prevent objdump from including it in kernel dumps
         *
         * Reason for having .init.ramfs above .init is to make sure that the
         * binary blob is tucked away to one side, reducing the displacement
index ad702b49aeb3b8d2a0306f209bf140acb5fd2beb..cae4a7aae0ed4e186addda91d54b02153ca7181c 100644 (file)
@@ -212,7 +212,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
        unsigned long flags;
 
        /* If range @start to @end is more than 32 TLB entries deep,
-        * its better to move to a new ASID rather than searching for
+        * it's better to move to a new ASID rather than searching for
         * individual entries and then shooting them down
         *
         * The calc above is rough, doesn't account for unaligned parts,
@@ -408,7 +408,7 @@ static void create_tlb(struct vm_area_struct *vma, unsigned long vaddr, pte_t *p
         * -More importantly it makes this handler inconsistent with fast-path
         *  TLB Refill handler which always deals with "current"
         *
-        * Lets see the use cases when current->mm != vma->mm and we land here
+        * Let's see the use cases when current->mm != vma->mm and we land here
         *  1. execve->copy_strings()->__get_user_pages->handle_mm_fault
         *     Here VM wants to pre-install a TLB entry for user stack while
         *     current->mm still points to pre-execve mm (hence the condition).
index e054780a8fe0c99b8a0103a3f0786d8dca3294fe..dc65e87a531fdb054466f8682af3649acb4d6fa3 100644 (file)
@@ -5,19 +5,19 @@
  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  *
  * Vineetg: April 2011 :
- *  -MMU v1: moved out legacy code into a seperate file
+ *  -MMU v1: moved out legacy code into a separate file
  *  -MMU v3: PD{0,1} bits layout changed: They don't overlap anymore,
  *      helps avoid a shift when preparing PD0 from PTE
  *
  * Vineetg: July 2009
- *  -For MMU V2, we need not do heuristics at the time of commiting a D-TLB
- *   entry, so that it doesn't knock out it's I-TLB entry
+ *  -For MMU V2, we need not do heuristics at the time of committing a D-TLB
+ *   entry, so that it doesn't knock out its I-TLB entry
  *  -Some more fine tuning:
  *   bmsk instead of add, asl.cc instead of branch, delay slot utilise etc
  *
  * Vineetg: July 2009
  *  -Practically rewrote the I/D TLB Miss handlers
- *   Now 40 and 135 instructions a peice as compared to 131 and 449 resp.
+ *   Now 40 and 135 instructions apiece as compared to 131 and 449 resp.
  *   Hence Leaner by 1.5 K
  *   Used Conditional arithmetic to replace excessive branching
  *   Also used short instructions wherever possible
index 4f609e9e510ef6e6821ef8f4d9cf0090a48c78f1..009d2c83242102c8e46a6f2019026b5d60a583ac 100644 (file)
 
                                        regulator-state-standby {
                                                regulator-on-in-suspend;
-                                               regulator-suspend-voltage = <1150000>;
+                                               regulator-suspend-microvolt = <1150000>;
                                                regulator-mode = <4>;
                                        };
 
 
                                        regulator-state-standby {
                                                regulator-on-in-suspend;
-                                               regulator-suspend-voltage = <1050000>;
+                                               regulator-suspend-microvolt = <1050000>;
                                                regulator-mode = <4>;
                                        };
 
                                        regulator-always-on;
 
                                        regulator-state-standby {
-                                               regulator-suspend-voltage = <1800000>;
+                                               regulator-suspend-microvolt = <1800000>;
                                                regulator-on-in-suspend;
                                        };
 
                                        regulator-always-on;
 
                                        regulator-state-standby {
-                                               regulator-suspend-voltage = <3300000>;
+                                               regulator-suspend-microvolt = <3300000>;
                                                regulator-on-in-suspend;
                                        };
 
index 217e9b96c61e5dea644c6b2f46d5807f58312b38..20b2497657ae48e691f06424ff688e27073bb63f 100644 (file)
 
                                        regulator-state-standby {
                                                regulator-on-in-suspend;
-                                               regulator-suspend-voltage = <1150000>;
+                                               regulator-suspend-microvolt = <1150000>;
                                                regulator-mode = <4>;
                                        };
 
 
                                        regulator-state-standby {
                                                regulator-on-in-suspend;
-                                               regulator-suspend-voltage = <1050000>;
+                                               regulator-suspend-microvolt = <1050000>;
                                                regulator-mode = <4>;
                                        };
 
                                        regulator-always-on;
 
                                        regulator-state-standby {
-                                               regulator-suspend-voltage = <1800000>;
+                                               regulator-suspend-microvolt = <1800000>;
                                                regulator-on-in-suspend;
                                        };
 
                                        regulator-max-microvolt = <3700000>;
 
                                        regulator-state-standby {
-                                               regulator-suspend-voltage = <1800000>;
+                                               regulator-suspend-microvolt = <1800000>;
                                                regulator-on-in-suspend;
                                        };
 
index 3fdece5bd31f9d00de384b911ca554b93bbc33b0..5248a058230c86910ef587ffa4e044e8645e6b6c 100644 (file)
                     &pinctrl_usb_pwr>;
        dr_mode = "host";
        power-active-high;
+       over-current-active-low;
        disable-over-current;
        status = "okay";
 };
index 1d672457d02ff3fcdd849c57c9108f94a8563886..72b5cd697f5d94b742fb59b98913c975838de871 100644 (file)
@@ -871,16 +871,11 @@ static inline void emit_a32_alu_r64(const bool is64, const s8 dst[],
 }
 
 /* dst = src (4 bytes)*/
-static inline void emit_a32_mov_r(const s8 dst, const s8 src, const u8 off,
-                                 struct jit_ctx *ctx) {
+static inline void emit_a32_mov_r(const s8 dst, const s8 src, struct jit_ctx *ctx) {
        const s8 *tmp = bpf2a32[TMP_REG_1];
        s8 rt;
 
        rt = arm_bpf_get_reg32(src, tmp[0], ctx);
-       if (off && off != 32) {
-               emit(ARM_LSL_I(rt, rt, 32 - off), ctx);
-               emit(ARM_ASR_I(rt, rt, 32 - off), ctx);
-       }
        arm_bpf_put_reg32(dst, rt, ctx);
 }
 
@@ -889,15 +884,15 @@ static inline void emit_a32_mov_r64(const bool is64, const s8 dst[],
                                  const s8 src[],
                                  struct jit_ctx *ctx) {
        if (!is64) {
-               emit_a32_mov_r(dst_lo, src_lo, 0, ctx);
+               emit_a32_mov_r(dst_lo, src_lo, ctx);
                if (!ctx->prog->aux->verifier_zext)
                        /* Zero out high 4 bytes */
                        emit_a32_mov_i(dst_hi, 0, ctx);
        } else if (__LINUX_ARM_ARCH__ < 6 &&
                   ctx->cpu_architecture < CPU_ARCH_ARMv5TE) {
                /* complete 8 byte move */
-               emit_a32_mov_r(dst_lo, src_lo, 0, ctx);
-               emit_a32_mov_r(dst_hi, src_hi, 0, ctx);
+               emit_a32_mov_r(dst_lo, src_lo, ctx);
+               emit_a32_mov_r(dst_hi, src_hi, ctx);
        } else if (is_stacked(src_lo) && is_stacked(dst_lo)) {
                const u8 *tmp = bpf2a32[TMP_REG_1];
 
@@ -917,17 +912,52 @@ static inline void emit_a32_mov_r64(const bool is64, const s8 dst[],
 static inline void emit_a32_movsx_r64(const bool is64, const u8 off, const s8 dst[], const s8 src[],
                                      struct jit_ctx *ctx) {
        const s8 *tmp = bpf2a32[TMP_REG_1];
-       const s8 *rt;
+       s8 rs;
+       s8 rd;
 
-       rt = arm_bpf_get_reg64(dst, tmp, ctx);
+       if (is_stacked(dst_lo))
+               rd = tmp[1];
+       else
+               rd = dst_lo;
+       rs = arm_bpf_get_reg32(src_lo, rd, ctx);
+       /* rs may be one of src[1], dst[1], or tmp[1] */
+
+       /* Sign extend rs if needed. If off == 32, lower 32-bits of src are moved to dst and sign
+        * extension only happens in the upper 64 bits.
+        */
+       if (off != 32) {
+               /* Sign extend rs into rd */
+               emit(ARM_LSL_I(rd, rs, 32 - off), ctx);
+               emit(ARM_ASR_I(rd, rd, 32 - off), ctx);
+       } else {
+               rd = rs;
+       }
+
+       /* Write rd to dst_lo
+        *
+        * Optimization:
+        * Assume:
+        * 1. dst == src and stacked.
+        * 2. off == 32
+        *
+        * In this case src_lo was loaded into rd(tmp[1]) but rd was not sign extended as off==32.
+        * So, we don't need to write rd back to dst_lo as they have the same value.
+        * This saves us one str instruction.
+        */
+       if (dst_lo != src_lo || off != 32)
+               arm_bpf_put_reg32(dst_lo, rd, ctx);
 
-       emit_a32_mov_r(dst_lo, src_lo, off, ctx);
        if (!is64) {
                if (!ctx->prog->aux->verifier_zext)
                        /* Zero out high 4 bytes */
                        emit_a32_mov_i(dst_hi, 0, ctx);
        } else {
-               emit(ARM_ASR_I(rt[0], rt[1], 31), ctx);
+               if (is_stacked(dst_hi)) {
+                       emit(ARM_ASR_I(tmp[0], rd, 31), ctx);
+                       arm_bpf_put_reg32(dst_hi, tmp[0], ctx);
+               } else {
+                       emit(ARM_ASR_I(dst_hi, rd, 31), ctx);
+               }
        }
 }
 
index af421ba24ce0c6daae4c015ab219e3c80fbc6fa0..d12b01c5f41b69029de04bc006be35c1ded3aeaa 100644 (file)
@@ -6,6 +6,7 @@
 /dts-v1/;
 
 #include "sun50i-h616.dtsi"
+#include "sun50i-h616-cpu-opp.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
        };
 };
 
+&cpu0 {
+       cpu-supply = <&reg_dcdc2>;
+};
+
 &mmc0 {
        vmmc-supply = <&reg_dldo1>;
        /* Card detection pin is not connected */
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616-cpu-opp.dtsi
new file mode 100644 (file)
index 0000000..aca22a7
--- /dev/null
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2023 Martin Botka <martin@somainline.org>
+
+/ {
+       cpu_opp_table: opp-table-cpu {
+               compatible = "allwinner,sun50i-h616-operating-points";
+               nvmem-cells = <&cpu_speed_grade>;
+               opp-shared;
+
+               opp-480000000 {
+                       opp-hz = /bits/ 64 <480000000>;
+                       opp-microvolt = <900000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+                       opp-supported-hw = <0x1f>;
+               };
+
+               opp-600000000 {
+                       opp-hz = /bits/ 64 <600000000>;
+                       opp-microvolt = <900000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+                       opp-supported-hw = <0x12>;
+               };
+
+               opp-720000000 {
+                       opp-hz = /bits/ 64 <720000000>;
+                       opp-microvolt = <900000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+                       opp-supported-hw = <0x0d>;
+               };
+
+               opp-792000000 {
+                       opp-hz = /bits/ 64 <792000000>;
+                       opp-microvolt-speed1 = <900000>;
+                       opp-microvolt-speed4 = <940000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+                       opp-supported-hw = <0x12>;
+               };
+
+               opp-936000000 {
+                       opp-hz = /bits/ 64 <936000000>;
+                       opp-microvolt = <900000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+                       opp-supported-hw = <0x0d>;
+               };
+
+               opp-1008000000 {
+                       opp-hz = /bits/ 64 <1008000000>;
+                       opp-microvolt-speed0 = <950000>;
+                       opp-microvolt-speed1 = <940000>;
+                       opp-microvolt-speed2 = <950000>;
+                       opp-microvolt-speed3 = <950000>;
+                       opp-microvolt-speed4 = <1020000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+                       opp-supported-hw = <0x1f>;
+               };
+
+               opp-1104000000 {
+                       opp-hz = /bits/ 64 <1104000000>;
+                       opp-microvolt-speed0 = <1000000>;
+                       opp-microvolt-speed2 = <1000000>;
+                       opp-microvolt-speed3 = <1000000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+                       opp-supported-hw = <0x0d>;
+               };
+
+               opp-1200000000 {
+                       opp-hz = /bits/ 64 <1200000000>;
+                       opp-microvolt-speed0 = <1050000>;
+                       opp-microvolt-speed1 = <1020000>;
+                       opp-microvolt-speed2 = <1050000>;
+                       opp-microvolt-speed3 = <1050000>;
+                       opp-microvolt-speed4 = <1100000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+                       opp-supported-hw = <0x1f>;
+               };
+
+               opp-1320000000 {
+                       opp-hz = /bits/ 64 <1320000000>;
+                       opp-microvolt = <1100000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+                       opp-supported-hw = <0x1d>;
+               };
+
+               opp-1416000000 {
+                       opp-hz = /bits/ 64 <1416000000>;
+                       opp-microvolt = <1100000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+                       opp-supported-hw = <0x0d>;
+               };
+
+               opp-1512000000 {
+                       opp-hz = /bits/ 64 <1512000000>;
+                       opp-microvolt-speed1 = <1100000>;
+                       opp-microvolt-speed3 = <1100000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+                       opp-supported-hw = <0x0a>;
+               };
+       };
+};
+
+&cpu0 {
+       operating-points-v2 = <&cpu_opp_table>;
+};
+
+&cpu1 {
+       operating-points-v2 = <&cpu_opp_table>;
+};
+
+&cpu2 {
+       operating-points-v2 = <&cpu_opp_table>;
+};
+
+&cpu3 {
+       operating-points-v2 = <&cpu_opp_table>;
+};
index b5d713926a341a291d1eb4e649b7984cd8ebc9e4..a360d8567f95589832f4a402a88c1aae11ade033 100644 (file)
@@ -6,12 +6,17 @@
 /dts-v1/;
 
 #include "sun50i-h616-orangepi-zero.dtsi"
+#include "sun50i-h616-cpu-opp.dtsi"
 
 / {
        model = "OrangePi Zero2";
        compatible = "xunlong,orangepi-zero2", "allwinner,sun50i-h616";
 };
 
+&cpu0 {
+       cpu-supply = <&reg_dcdca>;
+};
+
 &emac0 {
        allwinner,rx-delay-ps = <3100>;
        allwinner,tx-delay-ps = <700>;
index 959b6fd18483b48eefc23b6eb634604d2a7a52e5..26d25b5b59e0f89360799404d9998ca612887aa7 100644 (file)
@@ -6,6 +6,7 @@
 /dts-v1/;
 
 #include "sun50i-h616.dtsi"
+#include "sun50i-h616-cpu-opp.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
        };
 };
 
+&cpu0 {
+       cpu-supply = <&reg_dcdca>;
+};
+
 &ehci0 {
        status = "okay";
 };
index b2e85e52d1a12217e94cfd3b64b00b131075e76c..c0fa466fa9f07f9173976bb9d7edf4eabfeac1b6 100644 (file)
@@ -26,6 +26,7 @@
                        reg = <0>;
                        enable-method = "psci";
                        clocks = <&ccu CLK_CPUX>;
+                       #cooling-cells = <2>;
                };
 
                cpu1: cpu@1 {
@@ -34,6 +35,7 @@
                        reg = <1>;
                        enable-method = "psci";
                        clocks = <&ccu CLK_CPUX>;
+                       #cooling-cells = <2>;
                };
 
                cpu2: cpu@2 {
@@ -42,6 +44,7 @@
                        reg = <2>;
                        enable-method = "psci";
                        clocks = <&ccu CLK_CPUX>;
+                       #cooling-cells = <2>;
                };
 
                cpu3: cpu@3 {
@@ -50,6 +53,7 @@
                        reg = <3>;
                        enable-method = "psci";
                        clocks = <&ccu CLK_CPUX>;
+                       #cooling-cells = <2>;
                };
        };
 
                        ths_calibration: thermal-sensor-calibration@14 {
                                reg = <0x14 0x8>;
                        };
+
+                       cpu_speed_grade: cpu-speed-grade@0 {
+                               reg = <0x0 2>;
+                       };
                };
 
                watchdog: watchdog@30090a0 {
index 8c1263a3939e768e6204674d04fbf1e199ba1c80..e92d150aaf1c154dd6f5d8e973a9f18762a71e38 100644 (file)
@@ -4,6 +4,11 @@
  */
 
 #include "sun50i-h616.dtsi"
+#include "sun50i-h616-cpu-opp.dtsi"
+
+&cpu0 {
+       cpu-supply = <&reg_dcdc2>;
+};
 
 &mmc2 {
        pinctrl-names = "default";
index 21ca1977055d95cccc085779ba08e582f3c90697..6a4f0da9723303968c64710e5a700d6d681e9ea3 100644 (file)
@@ -6,6 +6,7 @@
 /dts-v1/;
 
 #include "sun50i-h616.dtsi"
+#include "sun50i-h616-cpu-opp.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
        };
 };
 
+&cpu0 {
+       cpu-supply = <&reg_dcdc2>;
+};
+
 &ehci1 {
        status = "okay";
 };
index b3b1b8692125f9f75df58a4a464fb5a4f185d79c..e1cd7572a14cebf22fd53689f99035f9e0cbcd91 100644 (file)
@@ -6,12 +6,17 @@
 /dts-v1/;
 
 #include "sun50i-h616-orangepi-zero.dtsi"
+#include "sun50i-h616-cpu-opp.dtsi"
 
 / {
        model = "OrangePi Zero3";
        compatible = "xunlong,orangepi-zero3", "allwinner,sun50i-h618";
 };
 
+&cpu0 {
+       cpu-supply = <&reg_dcdc2>;
+};
+
 &emac0 {
        allwinner,tx-delay-ps = <700>;
        phy-mode = "rgmii-rxid";
index ac0a2b7ea6f31089fba1bae1d76fbffba859320f..a6458b7a867130491a0a2bbfa9ba5a9a454fc953 100644 (file)
@@ -6,6 +6,7 @@
 /dts-v1/;
 
 #include "sun50i-h616.dtsi"
+#include "sun50i-h616-cpu-opp.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
        };
 };
 
+&cpu0 {
+       cpu-supply = <&reg_dcdc2>;
+};
+
 &ehci0 {
        status = "okay";
 };
index bfc5c81a5bd4eb44b2fb4cdf57ded83ccf8cb6e8..8141926e4ef1424639a3196337c7e006f5f6995e 100644 (file)
                                         <&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF_ROOT>,
                                         <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>;
                                clock-names = "pclk", "wrap", "phy", "axi";
-                               assigned-clocks = <&clk IMX8MP_CLK_MEDIA_CAM1_PIX>,
+                               assigned-clocks = <&clk IMX8MP_CLK_MEDIA_CAM2_PIX>,
                                                  <&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF>;
                                assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>,
                                                         <&clk IMX8MP_CLK_24M>;
index 0c38f7b51763776cda640ab73f8513f4cce9f1e5..234e3b23d7a8d3206c1f5e74f875a4501eea3942 100644 (file)
 };
 
 &pio {
-       eth_default: eth_default {
+       eth_default: eth-default-pins {
                tx_pins {
                        pinmux = <MT2712_PIN_71_GBE_TXD3__FUNC_GBE_TXD3>,
                                 <MT2712_PIN_72_GBE_TXD2__FUNC_GBE_TXD2>,
                };
        };
 
-       eth_sleep: eth_sleep {
+       eth_sleep: eth-sleep-pins {
                tx_pins {
                        pinmux = <MT2712_PIN_71_GBE_TXD3__FUNC_GPIO71>,
                                 <MT2712_PIN_72_GBE_TXD2__FUNC_GPIO72>,
                };
        };
 
-       usb0_id_pins_float: usb0_iddig {
+       usb0_id_pins_float: usb0-iddig-pins {
                pins_iddig {
                        pinmux = <MT2712_PIN_12_IDDIG_P0__FUNC_IDDIG_A>;
                        bias-pull-up;
                };
        };
 
-       usb1_id_pins_float: usb1_iddig {
+       usb1_id_pins_float: usb1-iddig-pins {
                pins_iddig {
                        pinmux = <MT2712_PIN_14_IDDIG_P1__FUNC_IDDIG_B>;
                        bias-pull-up;
index 6d218caa198cfd304eb546988737b1dc261c34ed..082672efba0a3408e9a9bb47ffad26046f97c3a2 100644 (file)
                #clock-cells = <1>;
        };
 
-       infracfg: syscon@10001000 {
+       infracfg: clock-controller@10001000 {
                compatible = "mediatek,mt2712-infracfg", "syscon";
                reg = <0 0x10001000 0 0x1000>;
                #clock-cells = <1>;
+               #reset-cells = <1>;
        };
 
        pericfg: syscon@10003000 {
index 3ee9266fa8e985cedcd4177f04dfdff8a4b689f4..917fa39a74f8d7f3d07cb71b7f0533c0777b5583 100644 (file)
                clock-names = "hif_sel";
        };
 
-       cir: cir@10009000 {
+       cir: ir-receiver@10009000 {
                compatible = "mediatek,mt7622-cir";
                reg = <0 0x10009000 0 0x1000>;
                interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_LOW>;
                };
        };
 
-       apmixedsys: apmixedsys@10209000 {
-               compatible = "mediatek,mt7622-apmixedsys",
-                            "syscon";
+       apmixedsys: clock-controller@10209000 {
+               compatible = "mediatek,mt7622-apmixedsys";
                reg = <0 0x10209000 0 0x1000>;
                #clock-cells = <1>;
        };
 
-       topckgen: topckgen@10210000 {
-               compatible = "mediatek,mt7622-topckgen",
-                            "syscon";
+       topckgen: clock-controller@10210000 {
+               compatible = "mediatek,mt7622-topckgen";
                reg = <0 0x10210000 0 0x1000>;
                #clock-cells = <1>;
        };
                         <&pericfg CLK_PERI_AUXADC_PD>;
                clock-names = "therm", "auxadc";
                resets = <&pericfg MT7622_PERI_THERM_SW_RST>;
-               reset-names = "therm";
                mediatek,auxadc = <&auxadc>;
                mediatek,apmixedsys = <&apmixedsys>;
                nvmem-cells = <&thermal_calibration>;
                power-domains = <&scpsys MT7622_POWER_DOMAIN_WB>;
        };
 
-       ssusbsys: ssusbsys@1a000000 {
-               compatible = "mediatek,mt7622-ssusbsys",
-                            "syscon";
+       ssusbsys: clock-controller@1a000000 {
+               compatible = "mediatek,mt7622-ssusbsys";
                reg = <0 0x1a000000 0 0x1000>;
                #clock-cells = <1>;
                #reset-cells = <1>;
                };
        };
 
-       pciesys: pciesys@1a100800 {
-               compatible = "mediatek,mt7622-pciesys",
-                            "syscon";
+       pciesys: clock-controller@1a100800 {
+               compatible = "mediatek,mt7622-pciesys";
                reg = <0 0x1a100800 0 0x1000>;
                #clock-cells = <1>;
                #reset-cells = <1>;
                };
        };
 
-       hifsys: syscon@1af00000 {
-               compatible = "mediatek,mt7622-hifsys", "syscon";
+       hifsys: clock-controller@1af00000 {
+               compatible = "mediatek,mt7622-hifsys";
                reg = <0 0x1af00000 0 0x70>;
+               #clock-cells = <1>;
        };
 
-       ethsys: syscon@1b000000 {
+       ethsys: clock-controller@1b000000 {
                compatible = "mediatek,mt7622-ethsys",
                             "syscon";
                reg = <0 0x1b000000 0 0x1000>;
        };
 
        eth: ethernet@1b100000 {
-               compatible = "mediatek,mt7622-eth",
-                            "mediatek,mt2701-eth",
-                            "syscon";
+               compatible = "mediatek,mt7622-eth";
                reg = <0 0x1b100000 0 0x20000>;
                interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_LOW>,
                             <GIC_SPI 224 IRQ_TYPE_LEVEL_LOW>,
index e04b1c0c0ebbfb59e6e75318ebfaef1dfbe02997..ed79ad1ae8716e0f750e8b747eea930f496541cb 100644 (file)
 
 &cpu_thermal {
        cooling-maps {
-               cpu-active-high {
+               map-cpu-active-high {
                        /* active: set fan to cooling level 2 */
                        cooling-device = <&fan 2 2>;
                        trip = <&cpu_trip_active_high>;
                };
 
-               cpu-active-med {
+               map-cpu-active-med {
                        /* active: set fan to cooling level 1 */
                        cooling-device = <&fan 1 1>;
                        trip = <&cpu_trip_active_med>;
                };
 
-               cpu-active-low {
+               map-cpu-active-low {
                        /* active: set fan to cooling level 0 */
                        cooling-device = <&fan 0 0>;
                        trip = <&cpu_trip_active_low>;
index b3f416b9a7a4da6c15c040c160ee6d6203979aeb..559990dcd1d1790b2f985dda29e6bd2ebdfd08c0 100644 (file)
                        reg = <0 0x1100c800 0 0x800>;
                        interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&infracfg CLK_INFRA_THERM_CK>,
-                                <&infracfg CLK_INFRA_ADC_26M_CK>,
-                                <&infracfg CLK_INFRA_ADC_FRC_CK>;
-                       clock-names = "therm", "auxadc", "adc_32k";
+                                <&infracfg CLK_INFRA_ADC_26M_CK>;
+                       clock-names = "therm", "auxadc";
                        nvmem-cells = <&thermal_calibration>;
                        nvmem-cell-names = "calibration-data";
                        #thermal-sensor-cells = <1>;
                         compatible = "mediatek,mt7986-ethsys",
                                      "syscon";
                         reg = <0 0x15000000 0 0x1000>;
-                        #address-cells = <1>;
-                        #size-cells = <1>;
                         #clock-cells = <1>;
                         #reset-cells = <1>;
                };
                                          <&topckgen CLK_TOP_SGM_325M_SEL>;
                        assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>,
                                                 <&apmixedsys CLK_APMIXED_SGMPLL>;
-                       #reset-cells = <1>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        mediatek,ethsys = <&ethsys>;
index 6bd7424ef66c53b48d89d07ca14d25e913fd1c98..100191c6453ba3b6f69762654e7ef421bf87cd30 100644 (file)
 };
 
 &mt6358_vgpu_reg {
-       regulator-min-microvolt = <625000>;
        regulator-max-microvolt = <900000>;
 
        regulator-coupled-with = <&mt6358_vsram_gpu_reg>;
index 93dfbf1302315d83c2a4c556694c4193ed56e8a3..774ae5d9143f1ea95cc15a7148b5ec54c7d8552a 100644 (file)
                        compatible = "mediatek,mt8183-mfgcfg", "syscon";
                        reg = <0 0x13000000 0 0x1000>;
                        #clock-cells = <1>;
+                       power-domains = <&spm MT8183_POWER_DOMAIN_MFG_ASYNC>;
                };
 
                gpu: gpu@13040000 {
index 3dea28f1d80612737c1309199d334734411aee07..1807e9d6cb0e4123329c5b369fc83a61f7677721 100644 (file)
                                 * regulator coupling requirements.
                                 */
                                regulator-name = "ppvar_dvdd_vgpu";
-                               regulator-min-microvolt = <600000>;
+                               regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <950000>;
                                regulator-ramp-delay = <6250>;
                                regulator-enable-ramp-delay = <200>;
index 9b738f6a5d213ada21fb98eef5ff223caa4dfdc7..7a704246678f03000c6640f5e3efc8d9fcb49884 100644 (file)
                        mt6315_6_vbuck1: vbuck1 {
                                regulator-compatible = "vbuck1";
                                regulator-name = "Vbcpu";
-                               regulator-min-microvolt = <300000>;
+                               regulator-min-microvolt = <400000>;
                                regulator-max-microvolt = <1193750>;
                                regulator-enable-ramp-delay = <256>;
                                regulator-allowed-modes = <0 1 2>;
                        mt6315_6_vbuck3: vbuck3 {
                                regulator-compatible = "vbuck3";
                                regulator-name = "Vlcpu";
-                               regulator-min-microvolt = <300000>;
+                               regulator-min-microvolt = <400000>;
                                regulator-max-microvolt = <1193750>;
                                regulator-enable-ramp-delay = <256>;
                                regulator-allowed-modes = <0 1 2>;
                        mt6315_7_vbuck1: vbuck1 {
                                regulator-compatible = "vbuck1";
                                regulator-name = "Vgpu";
-                               regulator-min-microvolt = <606250>;
+                               regulator-min-microvolt = <400000>;
                                regulator-max-microvolt = <800000>;
                                regulator-enable-ramp-delay = <256>;
                                regulator-allowed-modes = <0 1 2>;
index 05e401670bced3abf9eed4117739f2e4f24e99ee..84cbdf6e9eb0ca06b0187d14ab0c251ca1a9ef05 100644 (file)
                        reg = <0 0x14001000 0 0x1000>;
                        interrupts = <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH 0>;
                        clocks = <&mmsys CLK_MM_DISP_MUTEX0>;
+                       mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0x1000 0x1000>;
                        mediatek,gce-events = <CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_0>,
                                              <CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_1>;
                        power-domains = <&spm MT8192_POWER_DOMAIN_DISP>;
index f94c07f8b9334e817041a21e83515cb3dc274c40..4a11918da370483c287d5e03193e02656b617af1 100644 (file)
        status = "okay";
 };
 
+&cpu0 {
+       cpu-supply = <&mt6359_vcore_buck_reg>;
+};
+
+&cpu1 {
+       cpu-supply = <&mt6359_vcore_buck_reg>;
+};
+
+&cpu2 {
+       cpu-supply = <&mt6359_vcore_buck_reg>;
+};
+
+&cpu3 {
+       cpu-supply = <&mt6359_vcore_buck_reg>;
+};
+
+&cpu4 {
+       cpu-supply = <&mt6315_6_vbuck1>;
+};
+
+&cpu5 {
+       cpu-supply = <&mt6315_6_vbuck1>;
+};
+
+&cpu6 {
+       cpu-supply = <&mt6315_6_vbuck1>;
+};
+
+&cpu7 {
+       cpu-supply = <&mt6315_6_vbuck1>;
+};
+
 &dp_intf0 {
        status = "okay";
 
                        mt6315_6_vbuck1: vbuck1 {
                                regulator-compatible = "vbuck1";
                                regulator-name = "Vbcpu";
-                               regulator-min-microvolt = <300000>;
+                               regulator-min-microvolt = <400000>;
                                regulator-max-microvolt = <1193750>;
                                regulator-enable-ramp-delay = <256>;
                                regulator-ramp-delay = <6250>;
                        mt6315_7_vbuck1: vbuck1 {
                                regulator-compatible = "vbuck1";
                                regulator-name = "Vgpu";
-                               regulator-min-microvolt = <625000>;
+                               regulator-min-microvolt = <400000>;
                                regulator-max-microvolt = <1193750>;
                                regulator-enable-ramp-delay = <256>;
                                regulator-ramp-delay = <6250>;
index ea6dc220e1cce2181422fd33b9081ad1082e64b6..5d8b68f86ce44655664c07276e8ae813307cb248 100644 (file)
                        compatible = "mediatek,mt8195-vppsys0", "syscon";
                        reg = <0 0x14000000 0 0x1000>;
                        #clock-cells = <1>;
+                       mediatek,gce-client-reg = <&gce1 SUBSYS_1400XXXX 0 0x1000>;
                };
 
                dma-controller@14001000 {
                        compatible = "mediatek,mt8195-vppsys1", "syscon";
                        reg = <0 0x14f00000 0 0x1000>;
                        #clock-cells = <1>;
+                       mediatek,gce-client-reg = <&gce1 SUBSYS_14f0XXXX 0 0x1000>;
                };
 
                mutex@14f01000 {
                        reg = <0 0x1c01a000 0 0x1000>;
                        mboxes = <&gce0 0 CMDQ_THR_PRIO_4>;
                        #clock-cells = <1>;
+                       mediatek,gce-client-reg = <&gce0 SUBSYS_1c01XXXX 0xa000 0x1000>;
                };
 
 
                        interrupts = <GIC_SPI 658 IRQ_TYPE_LEVEL_HIGH 0>;
                        power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS0>;
                        clocks = <&vdosys0 CLK_VDO0_DISP_MUTEX0>;
+                       mediatek,gce-client-reg = <&gce0 SUBSYS_1c01XXXX 0x6000 0x1000>;
                        mediatek,gce-events = <CMDQ_EVENT_VDO0_DISP_STREAM_DONE_0>;
                };
 
                        power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>;
                        clocks = <&vdosys1 CLK_VDO1_DISP_MUTEX>;
                        clock-names = "vdo1_mutex";
+                       mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0x1000 0x1000>;
                        mediatek,gce-events = <CMDQ_EVENT_VDO1_STREAM_DONE_ENG_0>;
                };
 
index 7e7f0f0fb41ba03fe39095c7d1b5e2e24ac3136d..41f51d32611107ef84d30034d703c89b32f7dec2 100644 (file)
                        compatible = "qcom,sc7280-adsp-pas";
                        reg = <0 0x03700000 0 0x100>;
 
-                       interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>,
                                              <&adsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&adsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&adsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
                        compatible = "qcom,sc7280-cdsp-pas";
                        reg = <0 0x0a300000 0 0x10000>;
 
-                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
                                              <&cdsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&cdsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&cdsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
index 32afc78d5b769d56d6f316b2bbd34343a2497b56..053f7861c3ceced82c3dfb0cf539f94c9c2f64a5 100644 (file)
                        resets = <&gcc GCC_USB30_SEC_BCR>;
                        power-domains = <&gcc USB30_SEC_GDSC>;
                        interrupts-extended = <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
-                                             <&pdc 7 IRQ_TYPE_LEVEL_HIGH>,
+                                             <&pdc 40 IRQ_TYPE_LEVEL_HIGH>,
                                              <&pdc 10 IRQ_TYPE_EDGE_BOTH>,
                                              <&pdc 11 IRQ_TYPE_EDGE_BOTH>;
                        interrupt-names = "hs_phy_irq", "ss_phy_irq",
index a5b194813079e9779e7913a4054a413af3a14750..d0f82e12289e1b53f1d01592a2131932a48866c5 100644 (file)
                        reset-names = "pci";
 
                        power-domains = <&gcc PCIE_4_GDSC>;
+                       required-opps = <&rpmhpd_opp_nom>;
 
                        phys = <&pcie4_phy>;
                        phy-names = "pciephy";
                        reset-names = "pci";
 
                        power-domains = <&gcc PCIE_3B_GDSC>;
+                       required-opps = <&rpmhpd_opp_nom>;
 
                        phys = <&pcie3b_phy>;
                        phy-names = "pciephy";
                        reset-names = "pci";
 
                        power-domains = <&gcc PCIE_3A_GDSC>;
+                       required-opps = <&rpmhpd_opp_nom>;
 
                        phys = <&pcie3a_phy>;
                        phy-names = "pciephy";
                        reset-names = "pci";
 
                        power-domains = <&gcc PCIE_2B_GDSC>;
+                       required-opps = <&rpmhpd_opp_nom>;
 
                        phys = <&pcie2b_phy>;
                        phy-names = "pciephy";
                        reset-names = "pci";
 
                        power-domains = <&gcc PCIE_2A_GDSC>;
+                       required-opps = <&rpmhpd_opp_nom>;
 
                        phys = <&pcie2a_phy>;
                        phy-names = "pciephy";
                        compatible = "qcom,sc8280xp-adsp-pas";
                        reg = <0 0x03000000 0 0x100>;
 
-                       interrupts-extended = <&intc GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&intc GIC_SPI 162 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
                        compatible = "qcom,sc8280xp-nsp0-pas";
                        reg = <0 0x1b300000 0 0x100>;
 
-                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_nsp0_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_nsp0_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_nsp0_in 2 IRQ_TYPE_EDGE_RISING>,
                        compatible = "qcom,sc8280xp-nsp1-pas";
                        reg = <0 0x21300000 0 0x100>;
 
-                       interrupts-extended = <&intc GIC_SPI 887 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&intc GIC_SPI 887 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_nsp1_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_nsp1_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_nsp1_in 2 IRQ_TYPE_EDGE_RISING>,
index 24bcec3366efd58671cbcd6fa27cd0d807ab2d4f..0be053555602c0d3e1bd52888c05e841bb4de9ae 100644 (file)
                        compatible = "qcom,sm6350-adsp-pas";
                        reg = <0 0x03000000 0 0x100>;
 
-                       interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
                        compatible = "qcom,sm6350-cdsp-pas";
                        reg = <0 0x08300000 0 0x10000>;
 
-                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_cdsp_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_cdsp_in 2 IRQ_TYPE_EDGE_RISING>,
index 4386f8a9c636c1dd58a21ed8002d385c3d716c5c..f40509d91bbda8a73d9624ca78fcb3b03e2bf60c 100644 (file)
                        compatible = "qcom,sm6375-adsp-pas";
                        reg = <0 0x0a400000 0 0x100>;
 
-                       interrupts-extended = <&intc GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&intc GIC_SPI 282 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
index 39bd8f0eba1e653a7fe1b452cb7615317f3f6b68..7f2333c9d17d6d74ee3fe33a017e2fa03bcb3683 100644 (file)
                        compatible = "qcom,sm8250-slpi-pas";
                        reg = <0 0x05c00000 0 0x4000>;
 
-                       interrupts-extended = <&pdc 9 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&pdc 9 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_slpi_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_slpi_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_slpi_in 2 IRQ_TYPE_EDGE_RISING>,
                        compatible = "qcom,sm8250-cdsp-pas";
                        reg = <0 0x08300000 0 0x10000>;
 
-                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_cdsp_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_cdsp_in 2 IRQ_TYPE_EDGE_RISING>,
                        compatible = "qcom,sm8250-adsp-pas";
                        reg = <0 0x17300000 0 0x100>;
 
-                       interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
index b86be34a912b943e7649eecbd71fae2b78411e5f..024d2653cc3075126a59da6f099c5a14b18bc8d6 100644 (file)
                        ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>,
                                 <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>;
 
-                       /*
-                        * MSIs for BDF (1:0.0) only works with Device ID 0x5980.
-                        * Hence, the IDs are swapped.
-                        */
-                       msi-map = <0x0 &gic_its 0x5981 0x1>,
-                                 <0x100 &gic_its 0x5980 0x1>;
+                       msi-map = <0x0 &gic_its 0x5980 0x1>,
+                                 <0x100 &gic_its 0x5981 0x1>;
                        msi-map-mask = <0xff00>;
                        interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
                        ranges = <0x01000000 0x0 0x00000000 0x0 0x40200000 0x0 0x100000>,
                                 <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x1fd00000>;
 
-                       /*
-                        * MSIs for BDF (1:0.0) only works with Device ID 0x5a00.
-                        * Hence, the IDs are swapped.
-                        */
-                       msi-map = <0x0 &gic_its 0x5a01 0x1>,
-                                 <0x100 &gic_its 0x5a00 0x1>;
+                       msi-map = <0x0 &gic_its 0x5a00 0x1>,
+                                 <0x100 &gic_its 0x5a01 0x1>;
                        msi-map-mask = <0xff00>;
                        interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>,
index 3904348075f67945a9e54117a518631541806ad9..3348bc06db488a77e4dd17dff687ffbcfa1cfced 100644 (file)
                                        <&gem_noc MASTER_APPSS_PROC 0 &cnoc_main SLAVE_PCIE_0 0>;
                        interconnect-names = "pcie-mem", "cpu-pcie";
 
-                       /* Entries are reversed due to the unusual ITS DeviceID encoding */
-                       msi-map = <0x0 &gic_its 0x1401 0x1>,
-                                 <0x100 &gic_its 0x1400 0x1>;
+                       msi-map = <0x0 &gic_its 0x1400 0x1>,
+                                 <0x100 &gic_its 0x1401 0x1>;
                        iommu-map = <0x0   &apps_smmu 0x1400 0x1>,
                                    <0x100 &apps_smmu 0x1401 0x1>;
 
                                        <&gem_noc MASTER_APPSS_PROC 0 &cnoc_main SLAVE_PCIE_1 0>;
                        interconnect-names = "pcie-mem", "cpu-pcie";
 
-                       /* Entries are reversed due to the unusual ITS DeviceID encoding */
-                       msi-map = <0x0 &gic_its 0x1481 0x1>,
-                                 <0x100 &gic_its 0x1480 0x1>;
+                       msi-map = <0x0 &gic_its 0x1480 0x1>,
+                                 <0x100 &gic_its 0x1481 0x1>;
                        iommu-map = <0x0   &apps_smmu 0x1480 0x1>,
                                    <0x100 &apps_smmu 0x1481 0x1>;
 
index ba72d8f3842073fd481926009ce37075894dc8c8..eb117866e59ff861bf8a41827a44429e172d6010 100644 (file)
                        interrupt-map-mask = <0 0 0 0x7>;
                        #interrupt-cells = <1>;
 
-                       /* Entries are reversed due to the unusual ITS DeviceID encoding */
-                       msi-map = <0x0 &gic_its 0x1401 0x1>,
-                                 <0x100 &gic_its 0x1400 0x1>;
+                       msi-map = <0x0 &gic_its 0x1400 0x1>,
+                                 <0x100 &gic_its 0x1401 0x1>;
                        msi-map-mask = <0xff00>;
 
                        linux,pci-domain = <0>;
                        interrupt-map-mask = <0 0 0 0x7>;
                        #interrupt-cells = <1>;
 
-                       /* Entries are reversed due to the unusual ITS DeviceID encoding */
-                       msi-map = <0x0 &gic_its 0x1481 0x1>,
-                                 <0x100 &gic_its 0x1480 0x1>;
+                       msi-map = <0x0 &gic_its 0x1480 0x1>,
+                                 <0x100 &gic_its 0x1481 0x1>;
                        msi-map-mask = <0xff00>;
 
                        linux,pci-domain = <1>;
index 8e517f76189e19cb038dfa0d3557ef729c630b46..6b40082bac68ce92d87076f6ba7e0fd980dfb23c 100644 (file)
 
                domain-idle-states {
                        CLUSTER_CL4: cluster-sleep-0 {
-                               compatible = "arm,idle-state";
+                               compatible = "domain-idle-state";
                                idle-state-name = "l2-ret";
                                arm,psci-suspend-param = <0x01000044>;
                                entry-latency-us = <350>;
                        };
 
                        CLUSTER_CL5: cluster-sleep-1 {
-                               compatible = "arm,idle-state";
+                               compatible = "domain-idle-state";
                                idle-state-name = "ret-pll-off";
                                arm,psci-suspend-param = <0x01000054>;
                                entry-latency-us = <2200>;
index 5846a11f0e848fc059446a47b57ff732b45e9f4c..d5e035823eb5e430c896c3a20a4347ccd919cc50 100644 (file)
@@ -663,7 +663,7 @@ camera: &i2c7 {
                        port@1 {
                                reg = <1>;
 
-                               mipi1_in_panel: endpoint@1 {
+                               mipi1_in_panel: endpoint {
                                        remote-endpoint = <&mipi1_out_panel>;
                                };
                        };
@@ -689,7 +689,6 @@ camera: &i2c7 {
        ep-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
 
        /* PERST# asserted in S3 */
-       pcie-reset-suspend = <1>;
 
        vpcie3v3-supply = <&wlan_3v3>;
        vpcie1v8-supply = <&pp1800_pcie>;
index dfb2a0bdea5b736d7ce6554e22a60c01d0b31297..9586bb12a5d8f51dbf81e8c9c200d6bafa0ae3e2 100644 (file)
                                #size-cells = <0>;
 
                                interface@0 {   /* interface 0 of configuration 1 */
-                                       compatible = "usbbda,8156.config1.0";
+                                       compatible = "usbifbda,8156.config1.0";
                                        reg = <0 1>;
                                };
                        };
index 054c6a4d1a45f71c7951752cbe8e86bd4e24d6ab..294eb2de263debd89e7bbc1a41495fb5fdf782a3 100644 (file)
 };
 
 &pcie0 {
-       bus-scan-delay-ms = <1000>;
        ep-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_HIGH>;
        num-lanes = <4>;
        pinctrl-names = "default";
index 2c3984a880af64ceaf3f7ec1a09ceee02f0dffeb..f6f15946579ebfc32925256e2569535be5a48f89 100644 (file)
        num-lanes = <4>;
        pinctrl-names = "default";
        pinctrl-0 = <&pcie_clkreqn_cpm>;
+       vpcie3v3-supply = <&vcc3v3_baseboard>;
+       vpcie12v-supply = <&dc_12v>;
        status = "okay";
 };
 
index c08e69391c015405a5ea7de34e211ee12ee6c58a..ccbe3a7a1d2c2fd9c195a027976d2c076d4f7381 100644 (file)
                regulator-max-microvolt = <5000000>;
        };
 
+       vcca_0v9: vcca-0v9-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "vcca_0v9";
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <900000>;
+               regulator-max-microvolt = <900000>;
+               vin-supply = <&vcc_1v8>;
+       };
+
+       vcca_1v8: vcca-1v8-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "vcca_1v8";
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vcc3v3_sys>;
+       };
+
        vdd_log: vdd-log {
                compatible = "pwm-regulator";
                pwms = <&pwm2 0 25000 1>;
        gpio1830-supply = <&vcc_1v8>;
 };
 
-&pmu_io_domains {
-       status = "okay";
-       pmu1830-supply = <&vcc_1v8>;
+&pcie0 {
+       /* PCIe PHY supplies */
+       vpcie0v9-supply = <&vcca_0v9>;
+       vpcie1v8-supply = <&vcca_1v8>;
 };
 
-&pwm2 {
-       status = "okay";
+&pcie_clkreqn_cpm {
+       rockchip,pins =
+               <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>;
 };
 
 &pinctrl {
+       pinctrl-names = "default";
+       pinctrl-0 = <&q7_thermal_pin>;
+
+       gpios {
+               q7_thermal_pin: q7-thermal-pin {
+                       rockchip,pins =
+                               <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
        i2c8 {
                i2c8_xfer_a: i2c8-xfer {
                        rockchip,pins =
        usb3 {
                usb3_id: usb3-id {
                        rockchip,pins =
-                         <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+                         <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 };
 
+&pmu_io_domains {
+       status = "okay";
+       pmu1830-supply = <&vcc_1v8>;
+};
+
+&pwm2 {
+       status = "okay";
+};
+
 &sdhci {
        /*
         * Signal integrity isn't great at 200MHz but 100MHz has proven stable
index 6ecdf5d283390ae354063bc936468a17ddc0050b..c1194d1e438d0d0667ee3d7e0aa143856c87d319 100644 (file)
 
 &pcie2x1 {
        reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
-       disable-gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
        vpcie3v3-supply = <&vcc3v3_pcie>;
        status = "okay";
 };
index 7b5f3904ef6104754d8d2bc6c96ab668e5b3b230..c87fad2c34cba3bb58c4ab3ee61998128c1a566b 100644 (file)
 
                        vccio_sd: LDO_REG5 {
                                regulator-name = "vccio_sd";
+                               regulator-always-on;
+                               regulator-boot-on;
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <3300000>;
 
        #address-cells = <1>;
        #size-cells = <0>;
 
-       switch@0 {
+       switch@1f {
                compatible = "mediatek,mt7531";
-               reg = <0>;
+               reg = <0x1f>;
 
                ports {
                        #address-cells = <1>;
index a8a4cc190eb32e2cf18d9ab7f8549a96c12a6465..a3112d5df2008d99a236febbcadb883e036cb4e0 100644 (file)
 
 &pcie2x1 {
        reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>;
-       disable-gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_HIGH>;
        vpcie3v3-supply = <&vcc3v3_mini_pcie>;
        status = "okay";
 };
index cce1c8e835877c4341d90f2fe80da7c57dde8d0c..94ecb9b4f98f88c6ec0f93ff839f6a594eb75c19 100644 (file)
        pinctrl-0 = <&i2c7m0_xfer>;
        status = "okay";
 
-       es8316: audio-codec@11 {
+       es8316: audio-codec@10 {
                compatible = "everest,es8316";
-               reg = <0x11>;
+               reg = <0x10>;
                assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
                assigned-clock-rates = <12288000>;
                clocks = <&cru I2S0_8CH_MCLKOUT>;
index 1b606ea5b6cf2b32c72eab2bdac812b4a94d310c..1a604429fb266e687ab9fb20e7f157c78ac461c9 100644 (file)
                pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
                            <&rk806_dvs2_null>, <&rk806_dvs3_null>;
                spi-max-frequency = <1000000>;
+               system-power-controller;
 
                vcc1-supply = <&vcc5v0_sys>;
                vcc2-supply = <&vcc5v0_sys>;
                #gpio-cells = <2>;
 
                rk806_dvs1_null: dvs1-null-pins {
-                       pins = "gpio_pwrctrl2";
+                       pins = "gpio_pwrctrl1";
                        function = "pin_fun0";
                };
 
index 67414d72e2b6ef9308aa357c606f64d652c54075..22bbfbe729c11b6e0d30cd88a5fa144ba52a22e6 100644 (file)
                            <&rk806_dvs2_null>, <&rk806_dvs3_null>;
                pinctrl-names = "default";
                spi-max-frequency = <1000000>;
+               system-power-controller;
 
                vcc1-supply = <&vcc4v0_sys>;
                vcc2-supply = <&vcc4v0_sys>;
index 06234c3a15f3dbe7a5ee874c41b05bb72c2894d4..cb68adcabe0789201aa4b37befaa686c67dc7db7 100644 (file)
@@ -289,6 +289,11 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL)
        adr_l   x1, __hyp_text_end
        adr_l   x2, dcache_clean_poc
        blr     x2
+
+       mov_q   x0, INIT_SCTLR_EL2_MMU_OFF
+       pre_disable_mmu_workaround
+       msr     sctlr_el2, x0
+       isb
 0:
        mov_q   x0, HCR_HOST_NVHE_FLAGS
 
@@ -323,13 +328,11 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL)
        cbz     x0, 2f
 
        /* Set a sane SCTLR_EL1, the VHE way */
-       pre_disable_mmu_workaround
        msr_s   SYS_SCTLR_EL12, x1
        mov     x2, #BOOT_CPU_FLAG_E2H
        b       3f
 
 2:
-       pre_disable_mmu_workaround
        msr     sctlr_el1, x1
        mov     x2, xzr
 3:
index f48b8dab8b3d2fe175a02ddf3c81aa39dea5f16c..1d26bb5b02f4b592775dee6f964938f8ce4c866c 100644 (file)
@@ -338,12 +338,12 @@ int kvm_register_vgic_device(unsigned long type)
 int vgic_v2_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr,
                       struct vgic_reg_attr *reg_attr)
 {
-       int cpuid;
+       int cpuid = FIELD_GET(KVM_DEV_ARM_VGIC_CPUID_MASK, attr->attr);
 
-       cpuid = FIELD_GET(KVM_DEV_ARM_VGIC_CPUID_MASK, attr->attr);
-
-       reg_attr->vcpu = kvm_get_vcpu_by_id(dev->kvm, cpuid);
        reg_attr->addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+       reg_attr->vcpu = kvm_get_vcpu_by_id(dev->kvm, cpuid);
+       if (!reg_attr->vcpu)
+               return -EINVAL;
 
        return 0;
 }
index 0f0e10bb0a9540a9a18ab6c9cf0ed509d2a11e14..b872b003a55f3d672b638b88b75c4d5af39056ff 100644 (file)
@@ -276,7 +276,10 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma,
        pte_t *ptep = NULL;
 
        pgdp = pgd_offset(mm, addr);
-       p4dp = p4d_offset(pgdp, addr);
+       p4dp = p4d_alloc(mm, pgdp, addr);
+       if (!p4dp)
+               return NULL;
+
        pudp = pud_alloc(mm, p4dp, addr);
        if (!pudp)
                return NULL;
index 0c4e3ecf989d434ae96b6620e72448c57e9eeb67..0e270a1c51e6450f64cf30d2b357dc4a5472add1 100644 (file)
@@ -219,9 +219,6 @@ bool kernel_page_present(struct page *page)
        pte_t *ptep;
        unsigned long addr = (unsigned long)page_address(page);
 
-       if (!can_set_direct_map())
-               return true;
-
        pgdp = pgd_offset_k(addr);
        if (pgd_none(READ_ONCE(*pgdp)))
                return false;
index 122021f9bdfc87c3c9634d6801edad7845b9f96e..13eac43c632dfe793912ba310f7449d59e3bd9ed 100644 (file)
@@ -1844,15 +1844,15 @@ static void invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_link *l,
 
        emit_call(enter_prog, ctx);
 
+       /* save return value to callee saved register x20 */
+       emit(A64_MOV(1, A64_R(20), A64_R(0)), ctx);
+
        /* if (__bpf_prog_enter(prog) == 0)
         *         goto skip_exec_of_prog;
         */
        branch = ctx->image + ctx->idx;
        emit(A64_NOP, ctx);
 
-       /* save return value to callee saved register x20 */
-       emit(A64_MOV(1, A64_R(20), A64_R(0)), ctx);
-
        emit(A64_ADD_I(1, A64_R(0), A64_SP, args_off), ctx);
        if (!p->jited)
                emit_addr_mov_i64(A64_R(1), (const u64)p->insnsi, ctx);
index a5f300ec6f2808b8890ebc27d0de8a918eaa8636..54ad04dacdee94d869b2bd7d0ab92a92e60fe642 100644 (file)
@@ -595,7 +595,7 @@ config ARCH_SELECTS_CRASH_DUMP
        select RELOCATABLE
 
 config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
-       def_bool CRASH_CORE
+       def_bool CRASH_RESERVE
 
 config RELOCATABLE
        bool "Relocatable kernel"
diff --git a/arch/loongarch/include/asm/crash_core.h b/arch/loongarch/include/asm/crash_core.h
deleted file mode 100644 (file)
index 218bdbf..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-#ifndef _LOONGARCH_CRASH_CORE_H
-#define _LOONGARCH_CRASH_CORE_H
-
-#define CRASH_ALIGN                    SZ_2M
-
-#define CRASH_ADDR_LOW_MAX             SZ_4G
-#define CRASH_ADDR_HIGH_MAX            memblock_end_of_DRAM()
-
-extern phys_addr_t memblock_end_of_DRAM(void);
-
-#endif
diff --git a/arch/loongarch/include/asm/crash_reserve.h b/arch/loongarch/include/asm/crash_reserve.h
new file mode 100644 (file)
index 0000000..a1d9b84
--- /dev/null
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _LOONGARCH_CRASH_RESERVE_H
+#define _LOONGARCH_CRASH_RESERVE_H
+
+#define CRASH_ALIGN                    SZ_2M
+
+#define CRASH_ADDR_LOW_MAX             SZ_4G
+#define CRASH_ADDR_HIGH_MAX            memblock_end_of_DRAM()
+
+extern phys_addr_t memblock_end_of_DRAM(void);
+
+#endif
index 2a35a0bc2aaabf128cb5336d25dcbec1738d646b..52b638059e40b31645a62243e467c09e7d7ce0cf 100644 (file)
@@ -7,6 +7,14 @@
 #ifndef __LOONGARCH_PERF_EVENT_H__
 #define __LOONGARCH_PERF_EVENT_H__
 
+#include <asm/ptrace.h>
+
 #define perf_arch_bpf_user_pt_regs(regs) (struct user_pt_regs *)regs
 
+#define perf_arch_fetch_caller_regs(regs, __ip) { \
+       (regs)->csr_era = (__ip); \
+       (regs)->regs[3] = current_stack_pointer; \
+       (regs)->regs[22] = (unsigned long) __builtin_frame_address(0); \
+}
+
 #endif /* __LOONGARCH_PERF_EVENT_H__ */
index da7a3b5b9374aeaf8bc1009d49d3ee0265938e9e..e071f5e9e85802b2117ba89ce86e4ca3219864d2 100644 (file)
@@ -132,8 +132,6 @@ static __always_inline void invtlb_all(u32 op, u32 info, u64 addr)
                );
 }
 
-#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
-
 static void tlb_flush(struct mmu_gather *tlb);
 
 #define tlb_flush tlb_flush
index 0491bf453cd49601c4f8b7b35565ea4a2b83c689..cac7cba81b65f791cf5d3379dfda2daca01814ec 100644 (file)
@@ -884,4 +884,4 @@ static int __init init_hw_perf_events(void)
 
        return 0;
 }
-early_initcall(init_hw_perf_events);
+pure_initcall(init_hw_perf_events);
index 1fc2f6813ea027d43ccf24af8aade31f1093df62..97b40defde060846d95c9bc02c70b13ec53372a7 100644 (file)
@@ -202,10 +202,10 @@ good_area:
                if (!(vma->vm_flags & VM_WRITE))
                        goto bad_area;
        } else {
-               if (!(vma->vm_flags & VM_READ) && address != exception_era(regs))
-                       goto bad_area;
                if (!(vma->vm_flags & VM_EXEC) && address == exception_era(regs))
                        goto bad_area;
+               if (!(vma->vm_flags & (VM_READ | VM_WRITE)) && address != exception_era(regs))
+                       goto bad_area;
        }
 
        /*
index 74fb86b0d2097c658128a7f55bdce30110faeb87..7c728755852e1a2cfe06f46cca29eb339be8f4b8 100644 (file)
@@ -197,6 +197,9 @@ static struct skcipher_alg algs[] = {
 
 static int __init chacha_p10_init(void)
 {
+       if (!cpu_has_feature(CPU_FTR_ARCH_31))
+               return 0;
+
        static_branch_enable(&have_p10);
 
        return crypto_register_skciphers(algs, ARRAY_SIZE(algs));
@@ -204,10 +207,13 @@ static int __init chacha_p10_init(void)
 
 static void __exit chacha_p10_exit(void)
 {
+       if (!static_branch_likely(&have_p10))
+               return;
+
        crypto_unregister_skciphers(algs, ARRAY_SIZE(algs));
 }
 
-module_cpu_feature_match(PPC_MODULE_FEATURE_P10, chacha_p10_init);
+module_init(chacha_p10_init);
 module_exit(chacha_p10_exit);
 
 MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (P10 accelerated)");
index 23b77027c91637d0ef05e9952ebc1e72f7c24aa3..7a84069759b032dc61c2545773550417bf177d64 100644 (file)
@@ -44,9 +44,8 @@
 #define PLPKS_MAX_DATA_SIZE            4000
 
 // Timeouts for PLPKS operations
-#define PLPKS_MAX_TIMEOUT              5000 // msec
-#define PLPKS_FLUSH_SLEEP              10 // msec
-#define PLPKS_FLUSH_SLEEP_RANGE                400
+#define PLPKS_MAX_TIMEOUT              (5 * USEC_PER_SEC)
+#define PLPKS_FLUSH_SLEEP              10000 // usec
 
 struct plpks_var {
        char *component;
index 1185efebf032b6e7d2cf08db4c953938948a44b1..29a8c8e185851ba1e710146e3abae7d07e8a8dc8 100644 (file)
@@ -1285,15 +1285,14 @@ spapr_tce_platform_iommu_attach_dev(struct iommu_domain *platform_domain,
                                    struct device *dev)
 {
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
-       struct iommu_group *grp = iommu_group_get(dev);
        struct iommu_table_group *table_group;
+       struct iommu_group *grp;
 
        /* At first attach the ownership is already set */
-       if (!domain) {
-               iommu_group_put(grp);
+       if (!domain)
                return 0;
-       }
 
+       grp = iommu_group_get(dev);
        table_group = iommu_group_get_iommudata(grp);
        /*
         * The domain being set to PLATFORM from earlier
index e8c4129697b142ba48490481ee38793086e8425a..b1e6d275cda9ebaa7fa4659905691348d17faa75 100644 (file)
@@ -786,8 +786,16 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
         * parent bus. During reboot, there will be ibm,dma-window property to
         * define DMA window. For kdump, there will at least be default window or DDW
         * or both.
+        * There is an exception to the above. In case the PE goes into frozen
+        * state, firmware may not provide ibm,dma-window property at the time
+        * of LPAR boot up.
         */
 
+       if (!pdn) {
+               pr_debug("  no ibm,dma-window property !\n");
+               return;
+       }
+
        ppci = PCI_DN(pdn);
 
        pr_debug("  parent is %pOF, iommu_table: 0x%p\n",
index febe18f251d0cfb360a6330e4d0932e6941ae75e..4a595493d28ae3b808db8394e02c2b85b600b417 100644 (file)
@@ -415,8 +415,7 @@ static int plpks_confirm_object_flushed(struct label *label,
                        break;
                }
 
-               usleep_range(PLPKS_FLUSH_SLEEP,
-                            PLPKS_FLUSH_SLEEP + PLPKS_FLUSH_SLEEP_RANGE);
+               fsleep(PLPKS_FLUSH_SLEEP);
                timeout = timeout + PLPKS_FLUSH_SLEEP;
        } while (timeout < PLPKS_MAX_TIMEOUT);
 
@@ -464,9 +463,10 @@ int plpks_signed_update_var(struct plpks_var *var, u64 flags)
 
                continuetoken = retbuf[0];
                if (pseries_status_to_err(rc) == -EBUSY) {
-                       int delay_ms = get_longbusy_msecs(rc);
-                       mdelay(delay_ms);
-                       timeout += delay_ms;
+                       int delay_us = get_longbusy_msecs(rc) * 1000;
+
+                       fsleep(delay_us);
+                       timeout += delay_us;
                }
                rc = pseries_status_to_err(rc);
        } while (rc == -EBUSY && timeout < PLPKS_MAX_TIMEOUT);
index 910ba8837add866f622fba84f7c0c3535ee175e6..2acc7d876e1fb6aa5dc14ad3c3150f587ba1edea 100644 (file)
@@ -82,14 +82,14 @@ config ERRATA_THEAD
 
          Otherwise, please say "N" here to avoid unnecessary overhead.
 
-config ERRATA_THEAD_PBMT
-       bool "Apply T-Head memory type errata"
+config ERRATA_THEAD_MAE
+       bool "Apply T-Head's memory attribute extension (XTheadMae) errata"
        depends on ERRATA_THEAD && 64BIT && MMU
        select RISCV_ALTERNATIVE_EARLY
        default y
        help
-         This will apply the memory type errata to handle the non-standard
-         memory type bits in page-table-entries on T-Head SoCs.
+         This will apply the memory attribute extension errata to handle the
+         non-standard PTE utilization on T-Head SoCs (XTheadMae).
 
          If you don't know what to do here, say "Y".
 
index b1c410bbc1aece3c1fe0bea8cbd68271c8c0e29a..bf6a0a6318ee307085c3cc04c4056a0b63a000e9 100644 (file)
 #include <asm/patch.h>
 #include <asm/vendorid_list.h>
 
-static bool errata_probe_pbmt(unsigned int stage,
-                             unsigned long arch_id, unsigned long impid)
+#define CSR_TH_SXSTATUS                0x5c0
+#define SXSTATUS_MAEE          _AC(0x200000, UL)
+
+static bool errata_probe_mae(unsigned int stage,
+                            unsigned long arch_id, unsigned long impid)
 {
-       if (!IS_ENABLED(CONFIG_ERRATA_THEAD_PBMT))
+       if (!IS_ENABLED(CONFIG_ERRATA_THEAD_MAE))
                return false;
 
        if (arch_id != 0 || impid != 0)
                return false;
 
-       if (stage == RISCV_ALTERNATIVES_EARLY_BOOT ||
-           stage == RISCV_ALTERNATIVES_MODULE)
-               return true;
+       if (stage != RISCV_ALTERNATIVES_EARLY_BOOT &&
+           stage != RISCV_ALTERNATIVES_MODULE)
+               return false;
+
+       if (!(csr_read(CSR_TH_SXSTATUS) & SXSTATUS_MAEE))
+               return false;
 
-       return false;
+       return true;
 }
 
 /*
@@ -140,8 +146,8 @@ static u32 thead_errata_probe(unsigned int stage,
 {
        u32 cpu_req_errata = 0;
 
-       if (errata_probe_pbmt(stage, archid, impid))
-               cpu_req_errata |= BIT(ERRATA_THEAD_PBMT);
+       if (errata_probe_mae(stage, archid, impid))
+               cpu_req_errata |= BIT(ERRATA_THEAD_MAE);
 
        errata_probe_cmo(stage, archid, impid);
 
index 1f2dbfb8a8bfc8c9f5d46b9129c26756941c4918..efd851e1b48321e1f098008ce8fe7755ab49339d 100644 (file)
@@ -23,7 +23,7 @@
 #endif
 
 #ifdef CONFIG_ERRATA_THEAD
-#define        ERRATA_THEAD_PBMT 0
+#define        ERRATA_THEAD_MAE 0
 #define        ERRATA_THEAD_PMU 1
 #define        ERRATA_THEAD_NUMBER 2
 #endif
@@ -53,20 +53,20 @@ asm(ALTERNATIVE("sfence.vma %0", "sfence.vma", SIFIVE_VENDOR_ID,    \
  * in the default case.
  */
 #define ALT_SVPBMT_SHIFT 61
-#define ALT_THEAD_PBMT_SHIFT 59
+#define ALT_THEAD_MAE_SHIFT 59
 #define ALT_SVPBMT(_val, prot)                                         \
 asm(ALTERNATIVE_2("li %0, 0\t\nnop",                                   \
                  "li %0, %1\t\nslli %0,%0,%3", 0,                      \
                        RISCV_ISA_EXT_SVPBMT, CONFIG_RISCV_ISA_SVPBMT,  \
                  "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID,        \
-                       ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT)    \
+                       ERRATA_THEAD_MAE, CONFIG_ERRATA_THEAD_MAE)      \
                : "=r"(_val)                                            \
                : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT),               \
-                 "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT),            \
+                 "I"(prot##_THEAD >> ALT_THEAD_MAE_SHIFT),             \
                  "I"(ALT_SVPBMT_SHIFT),                                \
-                 "I"(ALT_THEAD_PBMT_SHIFT))
+                 "I"(ALT_THEAD_MAE_SHIFT))
 
-#ifdef CONFIG_ERRATA_THEAD_PBMT
+#ifdef CONFIG_ERRATA_THEAD_MAE
 /*
  * IO/NOCACHE memory types are handled together with svpbmt,
  * so on T-Head chips, check if no other memory type is set,
@@ -83,11 +83,11 @@ asm volatile(ALTERNATIVE(                                           \
        "slli    t3, t3, %3\n\t"                                        \
        "or      %0, %0, t3\n\t"                                        \
        "2:",  THEAD_VENDOR_ID,                                         \
-               ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT)            \
+               ERRATA_THEAD_MAE, CONFIG_ERRATA_THEAD_MAE)              \
        : "+r"(_val)                                                    \
-       : "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_PBMT_SHIFT),              \
-         "I"(_PAGE_PMA_THEAD >> ALT_THEAD_PBMT_SHIFT),                 \
-         "I"(ALT_THEAD_PBMT_SHIFT)                                     \
+       : "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_MAE_SHIFT),               \
+         "I"(_PAGE_PMA_THEAD >> ALT_THEAD_MAE_SHIFT),                  \
+         "I"(ALT_THEAD_MAE_SHIFT)                                      \
        : "t3")
 #else
 #define ALT_THEAD_PMA(_val)
index 2947423b5082e9b7f69b25a347685af499258161..115ac98b8d729da4e8f07f0f8f44e27438be107f 100644 (file)
@@ -89,7 +89,7 @@ typedef struct page *pgtable_t;
 #define PTE_FMT "%08lx"
 #endif
 
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && defined(CONFIG_MMU)
 /*
  * We override this value as its generic definition uses __pa too early in
  * the boot process (before kernel_map.va_pa_offset is set).
index 9f8ea0e33eb10424c5a05eb55849eacce627c3c3..6afd6bb4882eb28d1f1e96e451c7c92c20a6d2cc 100644 (file)
@@ -896,7 +896,7 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte)
 #define PAGE_SHARED            __pgprot(0)
 #define PAGE_KERNEL            __pgprot(0)
 #define swapper_pg_dir         NULL
-#define TASK_SIZE              0xffffffffUL
+#define TASK_SIZE              _AC(-1, UL)
 #define VMALLOC_START          _AC(0, UL)
 #define VMALLOC_END            TASK_SIZE
 
index 9f2a8e3ff2048e78201e188a5fc832a67429a06c..2902f68dc913aa620996da70d9b9bad39a133c2c 100644 (file)
@@ -54,7 +54,7 @@ struct riscv_hwprobe {
 #define                RISCV_HWPROBE_EXT_ZFHMIN        (1 << 28)
 #define                RISCV_HWPROBE_EXT_ZIHINTNTL     (1 << 29)
 #define                RISCV_HWPROBE_EXT_ZVFH          (1 << 30)
-#define                RISCV_HWPROBE_EXT_ZVFHMIN       (1 << 31)
+#define                RISCV_HWPROBE_EXT_ZVFHMIN       (1ULL << 31)
 #define                RISCV_HWPROBE_EXT_ZFA           (1ULL << 32)
 #define                RISCV_HWPROBE_EXT_ZTSO          (1ULL << 33)
 #define                RISCV_HWPROBE_EXT_ZACAS         (1ULL << 34)
index fe8e159394d8eeeeab34f83ae97ffadbec979b77..9687618432031fec77907d1c15fad0b9a3cc4c0a 100644 (file)
@@ -231,7 +231,7 @@ static void __init setup_bootmem(void)
         * In 64-bit, any use of __va/__pa before this point is wrong as we
         * did not know the start of DRAM before.
         */
-       if (IS_ENABLED(CONFIG_64BIT))
+       if (IS_ENABLED(CONFIG_64BIT) && IS_ENABLED(CONFIG_MMU))
                kernel_map.va_pa_offset = PAGE_OFFSET - phys_ram_base;
 
        /*
index 1adf2f39ce59cbb691b7f89ae9fc7a5127642ca4..ec9d692838fca54ee445d10ab3d862130338cd3b 100644 (file)
@@ -722,6 +722,9 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of
        if (ret)
                return ret;
 
+       /* store prog start time */
+       emit_mv(RV_REG_S1, RV_REG_A0, ctx);
+
        /* if (__bpf_prog_enter(prog) == 0)
         *      goto skip_exec_of_prog;
         */
@@ -729,9 +732,6 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of
        /* nop reserved for conditional jump */
        emit(rv_nop(), ctx);
 
-       /* store prog start time */
-       emit_mv(RV_REG_S1, RV_REG_A0, ctx);
-
        /* arg1: &args_off */
        emit_addi(RV_REG_A0, RV_REG_FP, -args_off, ctx);
        if (!p->jited)
index 99f7e1f2b70aff61da33cc06bc0e7455394150a8..99ea3f12c5d2ab2990c06b73602a3c513f361f7f 100644 (file)
@@ -125,8 +125,19 @@ struct s390_pxts_ctx {
 static inline int __paes_keyblob2pkey(struct key_blob *kb,
                                     struct pkey_protkey *pk)
 {
-       return pkey_keyblob2pkey(kb->key, kb->keylen,
-                                pk->protkey, &pk->len, &pk->type);
+       int i, ret = -EIO;
+
+       /* try three times in case of busy card */
+       for (i = 0; ret && i < 3; i++) {
+               if (ret == -EBUSY && in_task()) {
+                       if (msleep_interruptible(1000))
+                               return -EINTR;
+               }
+               ret = pkey_keyblob2pkey(kb->key, kb->keylen,
+                                       pk->protkey, &pk->len, &pk->type);
+       }
+
+       return ret;
 }
 
 static inline int __paes_convert_key(struct s390_paes_ctx *ctx)
index 4f21ae561e4ddc7af7bc7a21f848f0fe4315ab59..390906b8e386e609f760d891484133b1c0fbea79 100644 (file)
@@ -9,6 +9,7 @@
 #define CFI_DEF_CFA_OFFSET     .cfi_def_cfa_offset
 #define CFI_ADJUST_CFA_OFFSET  .cfi_adjust_cfa_offset
 #define CFI_RESTORE            .cfi_restore
+#define CFI_REL_OFFSET         .cfi_rel_offset
 
 #ifdef CONFIG_AS_CFI_VAL_OFFSET
 #define CFI_VAL_OFFSET         .cfi_val_offset
index 3dc85638bc63b7d96eb3ebc25c558cff967395c6..6a1e0fbbaa15b325c898548afe1189905d4b0520 100644 (file)
@@ -340,7 +340,8 @@ SYM_CODE_START(pgm_check_handler)
        mvc     __PT_LAST_BREAK(8,%r11),__LC_PGM_LAST_BREAK
        stctg   %c1,%c1,__PT_CR1(%r11)
 #if IS_ENABLED(CONFIG_KVM)
-       lg      %r12,__LC_GMAP
+       ltg     %r12,__LC_GMAP
+       jz      5f
        clc     __GMAP_ASCE(8,%r12), __PT_CR1(%r11)
        jne     5f
        BPENTER __SF_SIE_FLAGS(%r10),_TIF_ISOLATE_BP_GUEST
index 57f62596e53b958a2737f23f1985e5154179fd9e..85247ef5a41b89a390d3290cefb785c6c5a81ad6 100644 (file)
@@ -24,8 +24,10 @@ __kernel_\func:
        CFI_DEF_CFA_OFFSET (STACK_FRAME_OVERHEAD + WRAPPER_FRAME_SIZE)
        CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD
        stg     %r14,STACK_FRAME_OVERHEAD(%r15)
+       CFI_REL_OFFSET 14, STACK_FRAME_OVERHEAD
        brasl   %r14,__s390_vdso_\func
        lg      %r14,STACK_FRAME_OVERHEAD(%r15)
+       CFI_RESTORE 14
        aghi    %r15,WRAPPER_FRAME_SIZE
        CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD
        CFI_RESTORE 15
index 094b43b121cd5d8d8895af0f1c830ab5cfb1d355..12d22a7fa32fd27a97d111f7d36971ecc7461bf5 100644 (file)
@@ -2661,7 +2661,7 @@ static int __s390_enable_skey_hugetlb(pte_t *pte, unsigned long addr,
                return 0;
 
        start = pmd_val(*pmd) & HPAGE_MASK;
-       end = start + HPAGE_SIZE - 1;
+       end = start + HPAGE_SIZE;
        __storage_key_init_range(start, end);
        set_bit(PG_arch_1, &page->flags);
        cond_resched();
index c2e8242bd15dd0afb6454e9e71e9ca5ef969ba13..dc3db86e13ffb8c14ca607c6df86ede9d3cf6262 100644 (file)
@@ -139,7 +139,7 @@ static void clear_huge_pte_skeys(struct mm_struct *mm, unsigned long rste)
        }
 
        if (!test_and_set_bit(PG_arch_1, &page->flags))
-               __storage_key_init_range(paddr, paddr + size - 1);
+               __storage_key_init_range(paddr, paddr + size);
 }
 
 void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
index 4474bf32d0a4970daec7fad3f12f8aa4a9e43871..928820e61cb5020a1eeb3bcc99b0a72227ae6c82 100644 (file)
@@ -62,6 +62,7 @@ config X86
        select ACPI_HOTPLUG_CPU                 if ACPI_PROCESSOR && HOTPLUG_CPU
        select ARCH_32BIT_OFF_T                 if X86_32
        select ARCH_CLOCKSOURCE_INIT
+       select ARCH_CONFIGURES_CPU_MITIGATIONS
        select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
        select ARCH_ENABLE_HUGEPAGE_MIGRATION if X86_64 && HUGETLB_PAGE && MIGRATION
        select ARCH_ENABLE_MEMORY_HOTPLUG if X86_64
@@ -2488,17 +2489,21 @@ config PREFIX_SYMBOLS
        def_bool y
        depends on CALL_PADDING && !CFI_CLANG
 
-menuconfig SPECULATION_MITIGATIONS
-       bool "Mitigations for speculative execution vulnerabilities"
+menuconfig CPU_MITIGATIONS
+       bool "Mitigations for CPU vulnerabilities"
        default y
        help
-         Say Y here to enable options which enable mitigations for
-         speculative execution hardware vulnerabilities.
+         Say Y here to enable options which enable mitigations for hardware
+         vulnerabilities (usually related to speculative execution).
+         Mitigations can be disabled or restricted to SMT systems at runtime
+         via the "mitigations" kernel parameter.
 
-         If you say N, all mitigations will be disabled. You really
-         should know what you are doing to say so.
+         If you say N, all mitigations will be disabled.  This CANNOT be
+         overridden at runtime.
 
-if SPECULATION_MITIGATIONS
+         Say 'Y', unless you really know what you are doing.
+
+if CPU_MITIGATIONS
 
 config MITIGATION_PAGE_TABLE_ISOLATION
        bool "Remove the kernel mapping in user mode"
index 6de50b80702e61087c432faf580a0ab063d22507..51cc9c7cb9bdc0e1181d08e33c05b5cc1f177830 100644 (file)
@@ -255,6 +255,71 @@ __visible noinstr void do_int80_emulation(struct pt_regs *regs)
        instrumentation_end();
        syscall_exit_to_user_mode(regs);
 }
+
+#ifdef CONFIG_X86_FRED
+/*
+ * A FRED-specific INT80 handler is warranted for the follwing reasons:
+ *
+ * 1) As INT instructions and hardware interrupts are separate event
+ *    types, FRED does not preclude the use of vector 0x80 for external
+ *    interrupts. As a result, the FRED setup code does not reserve
+ *    vector 0x80 and calling int80_is_external() is not merely
+ *    suboptimal but actively incorrect: it could cause a system call
+ *    to be incorrectly ignored.
+ *
+ * 2) It is called only for handling vector 0x80 of event type
+ *    EVENT_TYPE_SWINT and will never be called to handle any external
+ *    interrupt (event type EVENT_TYPE_EXTINT).
+ *
+ * 3) FRED has separate entry flows depending on if the event came from
+ *    user space or kernel space, and because the kernel does not use
+ *    INT insns, the FRED kernel entry handler fred_entry_from_kernel()
+ *    falls through to fred_bad_type() if the event type is
+ *    EVENT_TYPE_SWINT, i.e., INT insns. So if the kernel is handling
+ *    an INT insn, it can only be from a user level.
+ *
+ * 4) int80_emulation() does a CLEAR_BRANCH_HISTORY. While FRED will
+ *    likely take a different approach if it is ever needed: it
+ *    probably belongs in either fred_intx()/ fred_other() or
+ *    asm_fred_entrypoint_user(), depending on if this ought to be done
+ *    for all entries from userspace or only system
+ *    calls.
+ *
+ * 5) INT $0x80 is the fast path for 32-bit system calls under FRED.
+ */
+DEFINE_FREDENTRY_RAW(int80_emulation)
+{
+       int nr;
+
+       enter_from_user_mode(regs);
+
+       instrumentation_begin();
+       add_random_kstack_offset();
+
+       /*
+        * FRED pushed 0 into regs::orig_ax and regs::ax contains the
+        * syscall number.
+        *
+        * User tracing code (ptrace or signal handlers) might assume
+        * that the regs::orig_ax contains a 32-bit number on invoking
+        * a 32-bit syscall.
+        *
+        * Establish the syscall convention by saving the 32bit truncated
+        * syscall number in regs::orig_ax and by invalidating regs::ax.
+        */
+       regs->orig_ax = regs->ax & GENMASK(31, 0);
+       regs->ax = -ENOSYS;
+
+       nr = syscall_32_enter(regs);
+
+       local_irq_enable();
+       nr = syscall_enter_from_user_mode_work(regs, nr);
+       do_syscall_32_irqs_on(regs, nr);
+
+       instrumentation_end();
+       syscall_exit_to_user_mode(regs);
+}
+#endif
 #else /* CONFIG_IA32_EMULATION */
 
 /* Handles int $0x80 on a 32bit kernel */
index ac120cbdaaf2b4c474954c9a9f148222a370a72a..89c1476fcdd9f95825c0dbbb320b86b66360ce9e 100644 (file)
@@ -28,9 +28,9 @@ static noinstr void fred_bad_type(struct pt_regs *regs, unsigned long error_code
        if (regs->fred_cs.sl > 0) {
                pr_emerg("PANIC: invalid or fatal FRED event; event type %u "
                         "vector %u error 0x%lx aux 0x%lx at %04x:%016lx\n",
-                        regs->fred_ss.type, regs->fred_ss.vector, regs->orig_ax,
+                        regs->fred_ss.type, regs->fred_ss.vector, error_code,
                         fred_event_data(regs), regs->cs, regs->ip);
-               die("invalid or fatal FRED event", regs, regs->orig_ax);
+               die("invalid or fatal FRED event", regs, error_code);
                panic("invalid or fatal FRED event");
        } else {
                unsigned long flags = oops_begin();
@@ -38,10 +38,10 @@ static noinstr void fred_bad_type(struct pt_regs *regs, unsigned long error_code
 
                pr_alert("BUG: invalid or fatal FRED event; event type %u "
                         "vector %u error 0x%lx aux 0x%lx at %04x:%016lx\n",
-                        regs->fred_ss.type, regs->fred_ss.vector, regs->orig_ax,
+                        regs->fred_ss.type, regs->fred_ss.vector, error_code,
                         fred_event_data(regs), regs->cs, regs->ip);
 
-               if (__die("Invalid or fatal FRED event", regs, regs->orig_ax))
+               if (__die("Invalid or fatal FRED event", regs, error_code))
                        sig = 0;
 
                oops_end(flags, regs, sig);
@@ -66,7 +66,7 @@ static noinstr void fred_intx(struct pt_regs *regs)
        /* INT80 */
        case IA32_SYSCALL_VECTOR:
                if (ia32_enabled())
-                       return int80_emulation(regs);
+                       return fred_int80_emulation(regs);
                fallthrough;
 #endif
 
index a3c0df11d0e6d8c36db77b59077fef711724b2db..2fb7d53cf3338d3c390fa1fe2f000cc622b3af03 100644 (file)
@@ -98,11 +98,6 @@ static int addr_to_vsyscall_nr(unsigned long addr)
 
 static bool write_ok_or_segv(unsigned long ptr, size_t size)
 {
-       /*
-        * XXX: if access_ok, get_user, and put_user handled
-        * sig_on_uaccess_err, this could go away.
-        */
-
        if (!access_ok((void __user *)ptr, size)) {
                struct thread_struct *thread = &current->thread;
 
@@ -120,10 +115,8 @@ static bool write_ok_or_segv(unsigned long ptr, size_t size)
 bool emulate_vsyscall(unsigned long error_code,
                      struct pt_regs *regs, unsigned long address)
 {
-       struct task_struct *tsk;
        unsigned long caller;
        int vsyscall_nr, syscall_nr, tmp;
-       int prev_sig_on_uaccess_err;
        long ret;
        unsigned long orig_dx;
 
@@ -172,8 +165,6 @@ bool emulate_vsyscall(unsigned long error_code,
                goto sigsegv;
        }
 
-       tsk = current;
-
        /*
         * Check for access_ok violations and find the syscall nr.
         *
@@ -234,12 +225,8 @@ bool emulate_vsyscall(unsigned long error_code,
                goto do_ret;  /* skip requested */
 
        /*
-        * With a real vsyscall, page faults cause SIGSEGV.  We want to
-        * preserve that behavior to make writing exploits harder.
+        * With a real vsyscall, page faults cause SIGSEGV.
         */
-       prev_sig_on_uaccess_err = current->thread.sig_on_uaccess_err;
-       current->thread.sig_on_uaccess_err = 1;
-
        ret = -EFAULT;
        switch (vsyscall_nr) {
        case 0:
@@ -262,23 +249,12 @@ bool emulate_vsyscall(unsigned long error_code,
                break;
        }
 
-       current->thread.sig_on_uaccess_err = prev_sig_on_uaccess_err;
-
 check_fault:
        if (ret == -EFAULT) {
                /* Bad news -- userspace fed a bad pointer to a vsyscall. */
                warn_bad_vsyscall(KERN_INFO, regs,
                                  "vsyscall fault (exploit attempt?)");
-
-               /*
-                * If we failed to generate a signal for any reason,
-                * generate one here.  (This should be impossible.)
-                */
-               if (WARN_ON_ONCE(!sigismember(&tsk->pending.signal, SIGBUS) &&
-                                !sigismember(&tsk->pending.signal, SIGSEGV)))
-                       goto sigsegv;
-
-               return true;  /* Don't emulate the ret. */
+               goto sigsegv;
        }
 
        regs->ax = ret;
index 78cd5084104e9c205a6e949f6ee1ce6b93060fb0..4367aa77cb8d9f6f18adabebe39d3ef0ddc4dcf5 100644 (file)
@@ -1693,6 +1693,7 @@ void x86_perf_get_lbr(struct x86_pmu_lbr *lbr)
        lbr->from = x86_pmu.lbr_from;
        lbr->to = x86_pmu.lbr_to;
        lbr->info = x86_pmu.lbr_info;
+       lbr->has_callstack = x86_pmu_has_lbr_callstack();
 }
 EXPORT_SYMBOL_GPL(x86_perf_get_lbr);
 
index fe1e7e3cc844a84e08908e44094d020d2fa2107a..63bdc6b85219716cd000aa2551ec5133bafeaec7 100644 (file)
@@ -79,6 +79,9 @@ do {                                                                  \
 #define __smp_mb__before_atomic()      do { } while (0)
 #define __smp_mb__after_atomic()       do { } while (0)
 
+/* Writing to CR3 provides a full memory barrier in switch_mm(). */
+#define smp_mb__after_switch_mm()      do { } while (0)
+
 #include <asm-generic/barrier.h>
 
 #endif /* _ASM_X86_BARRIER_H */
index c086699b0d0c59fc62834bb457963f1b81b541d3..aa6c8f8ca9588e90894750ce4f93226c05af9c23 100644 (file)
@@ -25,6 +25,7 @@ u64 cc_mkdec(u64 val);
 void cc_random_init(void);
 #else
 #define cc_vendor (CC_VENDOR_NONE)
+static const u64 cc_mask = 0;
 
 static inline u64 cc_mkenc(u64 val)
 {
index e8f58ddd06d97fbce6ef1f701f9f91766ef2847d..2e74a7f0e93575c3aa4180dc9ad4a9728f07700d 100644 (file)
@@ -17,6 +17,7 @@ extern bool e820__mapped_all(u64 start, u64 end, enum e820_type type);
 extern void e820__range_add   (u64 start, u64 size, enum e820_type type);
 extern u64  e820__range_update(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type);
 extern u64  e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool check_type);
+extern u64  e820__range_update_table(struct e820_table *t, u64 start, u64 size, enum e820_type old_type, enum e820_type new_type);
 
 extern void e820__print_table(char *who);
 extern int  e820__update_table(struct e820_table *table);
index 16e07a2eee195d48e29536dc69c5d6e975c99d7f..6efd1497b02636bcabfcbd10aa02a618a089c554 100644 (file)
@@ -855,6 +855,7 @@ struct kvm_vcpu_arch {
        int cpuid_nent;
        struct kvm_cpuid_entry2 *cpuid_entries;
        struct kvm_hypervisor_cpuid kvm_cpuid;
+       bool is_amd_compatible;
 
        /*
         * FIXME: Drop this macro and use KVM_NR_GOVERNED_FEATURES directly
index 3736b8a46c04de58784396e10b016c51966ed43f..7f1e17250546bdb02e948907e23598097652e85a 100644 (file)
@@ -555,6 +555,7 @@ struct x86_pmu_lbr {
        unsigned int    from;
        unsigned int    to;
        unsigned int    info;
+       bool            has_callstack;
 };
 
 extern void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap);
index 0b748ee16b3d94ea09516ee14e187dbebae0bf4a..9abb8cc4cd4747f4982655d425df997852b1553b 100644 (file)
 #define _COMMON_PAGE_CHG_MASK  (PTE_PFN_MASK | _PAGE_PCD | _PAGE_PWT | \
                                 _PAGE_SPECIAL | _PAGE_ACCESSED |       \
                                 _PAGE_DIRTY_BITS | _PAGE_SOFT_DIRTY |  \
-                                _PAGE_DEVMAP | _PAGE_ENC | _PAGE_UFFD_WP)
+                                _PAGE_DEVMAP | _PAGE_CC | _PAGE_UFFD_WP)
 #define _PAGE_CHG_MASK (_COMMON_PAGE_CHG_MASK | _PAGE_PAT)
 #define _HPAGE_CHG_MASK (_COMMON_PAGE_CHG_MASK | _PAGE_PSE | _PAGE_PAT_LARGE)
 
@@ -173,6 +173,7 @@ enum page_cache_mode {
 };
 #endif
 
+#define _PAGE_CC               (_AT(pteval_t, cc_mask))
 #define _PAGE_ENC              (_AT(pteval_t, sme_me_mask))
 
 #define _PAGE_CACHE_MASK       (_PAGE_PWT | _PAGE_PCD | _PAGE_PAT)
index 811548f131f4e30418bedfdf98f1f302fc06723d..78e51b0d6433d6685c725b558bdd578c8ca4d6e8 100644 (file)
@@ -472,7 +472,6 @@ struct thread_struct {
        unsigned long           iopl_emul;
 
        unsigned int            iopl_warn:1;
-       unsigned int            sig_on_uaccess_err:1;
 
        /*
         * Protection Keys Register for Userspace.  Loaded immediately on
index 7f57382afee41754beb8164244f199e4ac30a148..93ed60080cfe7b58dc0349ab34fdb7e5704abd81 100644 (file)
@@ -269,6 +269,7 @@ int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 asid, bool immut
 int rmp_make_shared(u64 pfn, enum pg_level level);
 void snp_leak_pages(u64 pfn, unsigned int npages);
 void kdump_sev_callback(void);
+void snp_fixup_e820_tables(void);
 #else
 static inline bool snp_probe_rmptable_info(void) { return false; }
 static inline int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level) { return -ENODEV; }
@@ -282,6 +283,7 @@ static inline int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 as
 static inline int rmp_make_shared(u64 pfn, enum pg_level level) { return -ENODEV; }
 static inline void snp_leak_pages(u64 pfn, unsigned int npages) {}
 static inline void kdump_sev_callback(void) { }
+static inline void snp_fixup_e820_tables(void) {}
 #endif
 
 #endif
index c342c4aa9c6848c607238dad1ff07105737d5873..803dcfb0e3469c6393a81e0ada1675ea56451eb7 100644 (file)
@@ -1771,7 +1771,7 @@ void x2apic_setup(void)
        __x2apic_enable();
 }
 
-static __init void apic_set_fixmap(void);
+static __init void apic_set_fixmap(bool read_apic);
 
 static __init void x2apic_disable(void)
 {
@@ -1793,7 +1793,12 @@ static __init void x2apic_disable(void)
        }
 
        __x2apic_disable();
-       apic_set_fixmap();
+       /*
+        * Don't reread the APIC ID as it was already done from
+        * check_x2apic() and the APIC driver still is a x2APIC variant,
+        * which fails to do the read after x2APIC was disabled.
+        */
+       apic_set_fixmap(false);
 }
 
 static __init void x2apic_enable(void)
@@ -2057,13 +2062,14 @@ void __init init_apic_mappings(void)
        }
 }
 
-static __init void apic_set_fixmap(void)
+static __init void apic_set_fixmap(bool read_apic)
 {
        set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
        apic_mmio_base = APIC_BASE;
        apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
                    apic_mmio_base, mp_lapic_addr);
-       apic_read_boot_cpu_id(false);
+       if (read_apic)
+               apic_read_boot_cpu_id(false);
 }
 
 void __init register_lapic_address(unsigned long address)
@@ -2073,7 +2079,7 @@ void __init register_lapic_address(unsigned long address)
        mp_lapic_addr = address;
 
        if (!x2apic_mode)
-               apic_set_fixmap();
+               apic_set_fixmap(true);
 }
 
 /*
index cb9eece55904d049edc600960bdaa0db58765459..307302af0aeee22d0f3871d06ee117bd6c82818d 100644 (file)
@@ -459,8 +459,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
 
        case 0x1a:
                switch (c->x86_model) {
-               case 0x00 ... 0x0f:
-               case 0x20 ... 0x2f:
+               case 0x00 ... 0x2f:
                case 0x40 ... 0x4f:
                case 0x70 ... 0x7f:
                        setup_force_cpu_cap(X86_FEATURE_ZEN5);
index ca295b0c1eeee05b812c27bb88bd814dba3c1f00..ab18185894dfd5e9c3f09f5fa39ac4c8ef72e7f4 100644 (file)
@@ -1652,7 +1652,8 @@ static void __init bhi_select_mitigation(void)
                return;
 
        /* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */
-       if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) {
+       if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
+           !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE)) {
                spec_ctrl_disable_kernel_rrsba();
                if (rrsba_disabled)
                        return;
@@ -2804,11 +2805,13 @@ static const char *spectre_bhi_state(void)
 {
        if (!boot_cpu_has_bug(X86_BUG_BHI))
                return "; BHI: Not affected";
-       else if  (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW))
+       else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW))
                return "; BHI: BHI_DIS_S";
-       else if  (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
+       else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
                return "; BHI: SW loop, KVM: SW loop";
-       else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && rrsba_disabled)
+       else if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
+                !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE) &&
+                rrsba_disabled)
                return "; BHI: Retpoline";
        else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT))
                return "; BHI: Vulnerable, KVM: SW loop";
index b7174209d855c634a701aaf489372b087f464006..946813d816bfc2948eccc823300db283f99f91d4 100644 (file)
@@ -44,7 +44,10 @@ static const struct cpuid_dep cpuid_deps[] = {
        { X86_FEATURE_F16C,                     X86_FEATURE_XMM2,     },
        { X86_FEATURE_AES,                      X86_FEATURE_XMM2      },
        { X86_FEATURE_SHA_NI,                   X86_FEATURE_XMM2      },
+       { X86_FEATURE_GFNI,                     X86_FEATURE_XMM2      },
        { X86_FEATURE_FMA,                      X86_FEATURE_AVX       },
+       { X86_FEATURE_VAES,                     X86_FEATURE_AVX       },
+       { X86_FEATURE_VPCLMULQDQ,               X86_FEATURE_AVX       },
        { X86_FEATURE_AVX2,                     X86_FEATURE_AVX,      },
        { X86_FEATURE_AVX512F,                  X86_FEATURE_AVX,      },
        { X86_FEATURE_AVX512IFMA,               X86_FEATURE_AVX512F   },
@@ -56,9 +59,6 @@ static const struct cpuid_dep cpuid_deps[] = {
        { X86_FEATURE_AVX512VL,                 X86_FEATURE_AVX512F   },
        { X86_FEATURE_AVX512VBMI,               X86_FEATURE_AVX512F   },
        { X86_FEATURE_AVX512_VBMI2,             X86_FEATURE_AVX512VL  },
-       { X86_FEATURE_GFNI,                     X86_FEATURE_AVX512VL  },
-       { X86_FEATURE_VAES,                     X86_FEATURE_AVX512VL  },
-       { X86_FEATURE_VPCLMULQDQ,               X86_FEATURE_AVX512VL  },
        { X86_FEATURE_AVX512_VNNI,              X86_FEATURE_AVX512VL  },
        { X86_FEATURE_AVX512_BITALG,            X86_FEATURE_AVX512VL  },
        { X86_FEATURE_AVX512_4VNNIW,            X86_FEATURE_AVX512F   },
index 6f1b379e3b3851bbef0b66945563076b8cde40c0..68b09f718f10e47b9efa59e017d7c1558be7f273 100644 (file)
@@ -532,9 +532,10 @@ u64 __init e820__range_update(u64 start, u64 size, enum e820_type old_type, enum
        return __e820__range_update(e820_table, start, size, old_type, new_type);
 }
 
-static u64 __init e820__range_update_kexec(u64 start, u64 size, enum e820_type old_type, enum e820_type  new_type)
+u64 __init e820__range_update_table(struct e820_table *t, u64 start, u64 size,
+                                   enum e820_type old_type, enum e820_type new_type)
 {
-       return __e820__range_update(e820_table_kexec, start, size, old_type, new_type);
+       return __e820__range_update(t, start, size, old_type, new_type);
 }
 
 /* Remove a range of memory from the E820 table: */
@@ -806,7 +807,7 @@ u64 __init e820__memblock_alloc_reserved(u64 size, u64 align)
 
        addr = memblock_phys_alloc(size, align);
        if (addr) {
-               e820__range_update_kexec(addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED);
+               e820__range_update_table(e820_table_kexec, addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED);
                pr_info("update e820_table_kexec for e820__memblock_alloc_reserved()\n");
                e820__update_table_kexec();
        }
index 7062b84dd467d62ac1aed8c4fe4bdb86d5a7ac61..6d3d20e3e43a9b005f725d1e89dcc8fd81560dcd 100644 (file)
@@ -139,7 +139,7 @@ void __show_regs(struct pt_regs *regs, enum show_regs_mode mode,
                       log_lvl, d3, d6, d7);
        }
 
-       if (cpu_feature_enabled(X86_FEATURE_OSPKE))
+       if (cr4 & X86_CR4_PKE)
                printk("%sPKRU: %08x\n", log_lvl, read_pkru());
 }
 
index 8b04958da5e7d6c4bd096cffdaa4874e73433846..b4f8fa0f722cd6749079ba81d69458200c5051bb 100644 (file)
@@ -1203,12 +1203,14 @@ static enum es_result vc_check_opcode_bytes(struct es_em_ctxt *ctxt,
                break;
 
        case SVM_EXIT_MONITOR:
-               if (opcode == 0x010f && modrm == 0xc8)
+               /* MONITOR and MONITORX instructions generate the same error code */
+               if (opcode == 0x010f && (modrm == 0xc8 || modrm == 0xfa))
                        return ES_OK;
                break;
 
        case SVM_EXIT_MWAIT:
-               if (opcode == 0x010f && modrm == 0xc9)
+               /* MWAIT and MWAITX instructions generate the same error code */
+               if (opcode == 0x010f && (modrm == 0xc9 || modrm == 0xfb))
                        return ES_OK;
                break;
 
index a88bb14266b69fe9805cb864cbe4c02e928e460b..addc44fc7187d63b5ed8c9acc7790efd61d4cf5c 100644 (file)
@@ -3,11 +3,6 @@
 ccflags-y += -I $(srctree)/arch/x86/kvm
 ccflags-$(CONFIG_KVM_WERROR) += -Werror
 
-ifeq ($(CONFIG_FRAME_POINTER),y)
-OBJECT_FILES_NON_STANDARD_vmx/vmenter.o := y
-OBJECT_FILES_NON_STANDARD_svm/vmenter.o := y
-endif
-
 include $(srctree)/virt/kvm/Makefile.kvm
 
 kvm-y                  += x86.o emulate.o i8259.o irq.o lapic.o \
index bfc0bfcb2bc60dd2860fa4617f3dc92dea1f3a97..77352a4abd87f839a0a5b7adfb54301cb13ce02c 100644 (file)
@@ -376,6 +376,7 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
 
        kvm_update_pv_runtime(vcpu);
 
+       vcpu->arch.is_amd_compatible = guest_cpuid_is_amd_or_hygon(vcpu);
        vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu);
        vcpu->arch.reserved_gpa_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu);
 
index 856e3037e74f3ffc7fdeb72f2067812080d71910..23dbb9eb277c7465f19bc5af137b79d5a2b894d1 100644 (file)
@@ -120,6 +120,16 @@ static inline bool guest_cpuid_is_intel(struct kvm_vcpu *vcpu)
        return best && is_guest_vendor_intel(best->ebx, best->ecx, best->edx);
 }
 
+static inline bool guest_cpuid_is_amd_compatible(struct kvm_vcpu *vcpu)
+{
+       return vcpu->arch.is_amd_compatible;
+}
+
+static inline bool guest_cpuid_is_intel_compatible(struct kvm_vcpu *vcpu)
+{
+       return !guest_cpuid_is_amd_compatible(vcpu);
+}
+
 static inline int guest_cpuid_family(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
index cf37586f04668df976c983e89b7c37ae3c58e23a..ebf41023be38293dbc248d75a7125b63cd46c189 100644 (file)
@@ -2776,7 +2776,8 @@ int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type)
                trig_mode = reg & APIC_LVT_LEVEL_TRIGGER;
 
                r = __apic_accept_irq(apic, mode, vector, 1, trig_mode, NULL);
-               if (r && lvt_type == APIC_LVTPC)
+               if (r && lvt_type == APIC_LVTPC &&
+                   guest_cpuid_is_intel_compatible(apic->vcpu))
                        kvm_lapic_set_reg(apic, APIC_LVTPC, reg | APIC_LVT_MASKED);
                return r;
        }
index 992e651540e8523aadbd15f2cb8dc748850c6a49..db007a4dffa2e1ae11fced21f052f7fd23f68a7e 100644 (file)
@@ -4935,7 +4935,7 @@ static void reset_guest_rsvds_bits_mask(struct kvm_vcpu *vcpu,
                                context->cpu_role.base.level, is_efer_nx(context),
                                guest_can_use(vcpu, X86_FEATURE_GBPAGES),
                                is_cr4_pse(context),
-                               guest_cpuid_is_amd_or_hygon(vcpu));
+                               guest_cpuid_is_amd_compatible(vcpu));
 }
 
 static void __reset_rsvds_bits_mask_ept(struct rsvd_bits_validate *rsvd_check,
@@ -5576,9 +5576,9 @@ void kvm_mmu_after_set_cpuid(struct kvm_vcpu *vcpu)
         * that problem is swept under the rug; KVM's CPUID API is horrific and
         * it's all but impossible to solve it without introducing a new API.
         */
-       vcpu->arch.root_mmu.root_role.word = 0;
-       vcpu->arch.guest_mmu.root_role.word = 0;
-       vcpu->arch.nested_mmu.root_role.word = 0;
+       vcpu->arch.root_mmu.root_role.invalid = 1;
+       vcpu->arch.guest_mmu.root_role.invalid = 1;
+       vcpu->arch.nested_mmu.root_role.invalid = 1;
        vcpu->arch.root_mmu.cpu_role.ext.valid = 0;
        vcpu->arch.guest_mmu.cpu_role.ext.valid = 0;
        vcpu->arch.nested_mmu.cpu_role.ext.valid = 0;
@@ -7399,7 +7399,8 @@ bool kvm_arch_post_set_memory_attributes(struct kvm *kvm,
                         * by the memslot, KVM can't use a hugepage due to the
                         * misaligned address regardless of memory attributes.
                         */
-                       if (gfn >= slot->base_gfn) {
+                       if (gfn >= slot->base_gfn &&
+                           gfn + nr_pages <= slot->base_gfn + slot->npages) {
                                if (hugepage_has_attrs(kvm, slot, gfn, level, attrs))
                                        hugepage_clear_mixed(slot, gfn, level);
                                else
index d078157e62aa4025e6a3a6411e0d6b118245f3b8..04c1f0957fea875a5a17b1eccc5efddb53996624 100644 (file)
@@ -1548,17 +1548,21 @@ void kvm_tdp_mmu_try_split_huge_pages(struct kvm *kvm,
        }
 }
 
-/*
- * Clear the dirty status of all the SPTEs mapping GFNs in the memslot. If
- * AD bits are enabled, this will involve clearing the dirty bit on each SPTE.
- * If AD bits are not enabled, this will require clearing the writable bit on
- * each SPTE. Returns true if an SPTE has been changed and the TLBs need to
- * be flushed.
- */
+static bool tdp_mmu_need_write_protect(struct kvm_mmu_page *sp)
+{
+       /*
+        * All TDP MMU shadow pages share the same role as their root, aside
+        * from level, so it is valid to key off any shadow page to determine if
+        * write protection is needed for an entire tree.
+        */
+       return kvm_mmu_page_ad_need_write_protect(sp) || !kvm_ad_enabled();
+}
+
 static bool clear_dirty_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
                           gfn_t start, gfn_t end)
 {
-       u64 dbit = kvm_ad_enabled() ? shadow_dirty_mask : PT_WRITABLE_MASK;
+       const u64 dbit = tdp_mmu_need_write_protect(root) ? PT_WRITABLE_MASK :
+                                                           shadow_dirty_mask;
        struct tdp_iter iter;
        bool spte_set = false;
 
@@ -1573,7 +1577,7 @@ retry:
                if (tdp_mmu_iter_cond_resched(kvm, &iter, false, true))
                        continue;
 
-               KVM_MMU_WARN_ON(kvm_ad_enabled() &&
+               KVM_MMU_WARN_ON(dbit == shadow_dirty_mask &&
                                spte_ad_need_write_protect(iter.old_spte));
 
                if (!(iter.old_spte & dbit))
@@ -1590,11 +1594,9 @@ retry:
 }
 
 /*
- * Clear the dirty status of all the SPTEs mapping GFNs in the memslot. If
- * AD bits are enabled, this will involve clearing the dirty bit on each SPTE.
- * If AD bits are not enabled, this will require clearing the writable bit on
- * each SPTE. Returns true if an SPTE has been changed and the TLBs need to
- * be flushed.
+ * Clear the dirty status (D-bit or W-bit) of all the SPTEs mapping GFNs in the
+ * memslot. Returns true if an SPTE has been changed and the TLBs need to be
+ * flushed.
  */
 bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm,
                                  const struct kvm_memory_slot *slot)
@@ -1610,18 +1612,11 @@ bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm,
        return spte_set;
 }
 
-/*
- * Clears the dirty status of all the 4k SPTEs mapping GFNs for which a bit is
- * set in mask, starting at gfn. The given memslot is expected to contain all
- * the GFNs represented by set bits in the mask. If AD bits are enabled,
- * clearing the dirty status will involve clearing the dirty bit on each SPTE
- * or, if AD bits are not enabled, clearing the writable bit on each SPTE.
- */
 static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root,
                                  gfn_t gfn, unsigned long mask, bool wrprot)
 {
-       u64 dbit = (wrprot || !kvm_ad_enabled()) ? PT_WRITABLE_MASK :
-                                                  shadow_dirty_mask;
+       const u64 dbit = (wrprot || tdp_mmu_need_write_protect(root)) ? PT_WRITABLE_MASK :
+                                                                       shadow_dirty_mask;
        struct tdp_iter iter;
 
        lockdep_assert_held_write(&kvm->mmu_lock);
@@ -1633,7 +1628,7 @@ static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root,
                if (!mask)
                        break;
 
-               KVM_MMU_WARN_ON(kvm_ad_enabled() &&
+               KVM_MMU_WARN_ON(dbit == shadow_dirty_mask &&
                                spte_ad_need_write_protect(iter.old_spte));
 
                if (iter.level > PG_LEVEL_4K ||
@@ -1659,11 +1654,9 @@ static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root,
 }
 
 /*
- * Clears the dirty status of all the 4k SPTEs mapping GFNs for which a bit is
- * set in mask, starting at gfn. The given memslot is expected to contain all
- * the GFNs represented by set bits in the mask. If AD bits are enabled,
- * clearing the dirty status will involve clearing the dirty bit on each SPTE
- * or, if AD bits are not enabled, clearing the writable bit on each SPTE.
+ * Clear the dirty status (D-bit or W-bit) of all the 4k SPTEs mapping GFNs for
+ * which a bit is set in mask, starting at gfn. The given memslot is expected to
+ * contain all the GFNs represented by set bits in the mask.
  */
 void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm,
                                       struct kvm_memory_slot *slot,
index c397b28e3d1b680788249daa32f36c12c80bd1a1..a593b03c9aed677efb34c5925c57887023bae0f4 100644 (file)
@@ -775,8 +775,20 @@ void kvm_pmu_refresh(struct kvm_vcpu *vcpu)
        pmu->pebs_data_cfg_mask = ~0ull;
        bitmap_zero(pmu->all_valid_pmc_idx, X86_PMC_IDX_MAX);
 
-       if (vcpu->kvm->arch.enable_pmu)
-               static_call(kvm_x86_pmu_refresh)(vcpu);
+       if (!vcpu->kvm->arch.enable_pmu)
+               return;
+
+       static_call(kvm_x86_pmu_refresh)(vcpu);
+
+       /*
+        * At RESET, both Intel and AMD CPUs set all enable bits for general
+        * purpose counters in IA32_PERF_GLOBAL_CTRL (so that software that
+        * was written for v1 PMUs don't unknowingly leave GP counters disabled
+        * in the global controls).  Emulate that behavior when refreshing the
+        * PMU so that userspace doesn't need to manually set PERF_GLOBAL_CTRL.
+        */
+       if (kvm_pmu_has_perf_global_ctrl(pmu) && pmu->nr_arch_gp_counters)
+               pmu->global_ctrl = GENMASK_ULL(pmu->nr_arch_gp_counters - 1, 0);
 }
 
 void kvm_pmu_init(struct kvm_vcpu *vcpu)
index 61a7531d41b019a7f263b9c4e02ccfdf960dd09f..759581bb2128da1829b52e854329b6151147c9f8 100644 (file)
@@ -434,7 +434,7 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr,
        /* Avoid using vmalloc for smaller buffers. */
        size = npages * sizeof(struct page *);
        if (size > PAGE_SIZE)
-               pages = __vmalloc(size, GFP_KERNEL_ACCOUNT | __GFP_ZERO);
+               pages = __vmalloc(size, GFP_KERNEL_ACCOUNT);
        else
                pages = kmalloc(size, GFP_KERNEL_ACCOUNT);
 
index d1a9f9951635819c7a585882f06bcf6415ac2cdc..9aaf83c8d57df7d3877484a87060769956dbb9cb 100644 (file)
@@ -1503,6 +1503,11 @@ static void svm_vcpu_free(struct kvm_vcpu *vcpu)
        __free_pages(virt_to_page(svm->msrpm), get_order(MSRPM_SIZE));
 }
 
+static struct sev_es_save_area *sev_es_host_save_area(struct svm_cpu_data *sd)
+{
+       return page_address(sd->save_area) + 0x400;
+}
+
 static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -1519,12 +1524,8 @@ static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
         * or subsequent vmload of host save area.
         */
        vmsave(sd->save_area_pa);
-       if (sev_es_guest(vcpu->kvm)) {
-               struct sev_es_save_area *hostsa;
-               hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400);
-
-               sev_es_prepare_switch_to_guest(hostsa);
-       }
+       if (sev_es_guest(vcpu->kvm))
+               sev_es_prepare_switch_to_guest(sev_es_host_save_area(sd));
 
        if (tsc_scaling)
                __svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio);
@@ -4101,6 +4102,7 @@ static fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
 
 static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_intercepted)
 {
+       struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
        struct vcpu_svm *svm = to_svm(vcpu);
 
        guest_state_enter_irqoff();
@@ -4108,7 +4110,8 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_in
        amd_clear_divider();
 
        if (sev_es_guest(vcpu->kvm))
-               __svm_sev_es_vcpu_run(svm, spec_ctrl_intercepted);
+               __svm_sev_es_vcpu_run(svm, spec_ctrl_intercepted,
+                                     sev_es_host_save_area(sd));
        else
                __svm_vcpu_run(svm, spec_ctrl_intercepted);
 
index 7f1fbd874c4582b0b6d3735b62c3c85de2021074..33878efdebc82987efb574ce1e49e2f3df5637b8 100644 (file)
@@ -698,7 +698,8 @@ struct page *snp_safe_alloc_page(struct kvm_vcpu *vcpu);
 
 /* vmenter.S */
 
-void __svm_sev_es_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted);
+void __svm_sev_es_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted,
+                          struct sev_es_save_area *hostsa);
 void __svm_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted);
 
 #define DEFINE_KVM_GHCB_ACCESSORS(field)                                               \
index 187018c424bfb4ba8cadfa71a0f4ec7d4c63d766..a0c8eb37d3e1c62dc4390e6b61ccbbeff6845bff 100644 (file)
@@ -3,6 +3,7 @@
 #include <asm/asm.h>
 #include <asm/asm-offsets.h>
 #include <asm/bitsperlong.h>
+#include <asm/frame.h>
 #include <asm/kvm_vcpu_regs.h>
 #include <asm/nospec-branch.h>
 #include "kvm-asm-offsets.h"
@@ -67,7 +68,7 @@
                "", X86_FEATURE_V_SPEC_CTRL
 901:
 .endm
-.macro RESTORE_HOST_SPEC_CTRL_BODY
+.macro RESTORE_HOST_SPEC_CTRL_BODY spec_ctrl_intercepted:req
 900:
        /* Same for after vmexit.  */
        mov $MSR_IA32_SPEC_CTRL, %ecx
@@ -76,7 +77,7 @@
         * Load the value that the guest had written into MSR_IA32_SPEC_CTRL,
         * if it was not intercepted during guest execution.
         */
-       cmpb $0, (%_ASM_SP)
+       cmpb $0, \spec_ctrl_intercepted
        jnz 998f
        rdmsr
        movl %eax, SVM_spec_ctrl(%_ASM_DI)
  */
 SYM_FUNC_START(__svm_vcpu_run)
        push %_ASM_BP
+       mov  %_ASM_SP, %_ASM_BP
 #ifdef CONFIG_X86_64
        push %r15
        push %r14
@@ -268,7 +270,7 @@ SYM_FUNC_START(__svm_vcpu_run)
        RET
 
        RESTORE_GUEST_SPEC_CTRL_BODY
-       RESTORE_HOST_SPEC_CTRL_BODY
+       RESTORE_HOST_SPEC_CTRL_BODY (%_ASM_SP)
 
 10:    cmpb $0, _ASM_RIP(kvm_rebooting)
        jne 2b
@@ -290,66 +292,68 @@ SYM_FUNC_START(__svm_vcpu_run)
 
 SYM_FUNC_END(__svm_vcpu_run)
 
+#ifdef CONFIG_KVM_AMD_SEV
+
+
+#ifdef CONFIG_X86_64
+#define SEV_ES_GPRS_BASE 0x300
+#define SEV_ES_RBX     (SEV_ES_GPRS_BASE + __VCPU_REGS_RBX * WORD_SIZE)
+#define SEV_ES_RBP     (SEV_ES_GPRS_BASE + __VCPU_REGS_RBP * WORD_SIZE)
+#define SEV_ES_RSI     (SEV_ES_GPRS_BASE + __VCPU_REGS_RSI * WORD_SIZE)
+#define SEV_ES_RDI     (SEV_ES_GPRS_BASE + __VCPU_REGS_RDI * WORD_SIZE)
+#define SEV_ES_R12     (SEV_ES_GPRS_BASE + __VCPU_REGS_R12 * WORD_SIZE)
+#define SEV_ES_R13     (SEV_ES_GPRS_BASE + __VCPU_REGS_R13 * WORD_SIZE)
+#define SEV_ES_R14     (SEV_ES_GPRS_BASE + __VCPU_REGS_R14 * WORD_SIZE)
+#define SEV_ES_R15     (SEV_ES_GPRS_BASE + __VCPU_REGS_R15 * WORD_SIZE)
+#endif
+
 /**
  * __svm_sev_es_vcpu_run - Run a SEV-ES vCPU via a transition to SVM guest mode
  * @svm:       struct vcpu_svm *
  * @spec_ctrl_intercepted: bool
  */
 SYM_FUNC_START(__svm_sev_es_vcpu_run)
-       push %_ASM_BP
-#ifdef CONFIG_X86_64
-       push %r15
-       push %r14
-       push %r13
-       push %r12
-#else
-       push %edi
-       push %esi
-#endif
-       push %_ASM_BX
+       FRAME_BEGIN
 
        /*
-        * Save variables needed after vmexit on the stack, in inverse
-        * order compared to when they are needed.
+        * Save non-volatile (callee-saved) registers to the host save area.
+        * Except for RAX and RSP, all GPRs are restored on #VMEXIT, but not
+        * saved on VMRUN.
         */
+       mov %rbp, SEV_ES_RBP (%rdx)
+       mov %r15, SEV_ES_R15 (%rdx)
+       mov %r14, SEV_ES_R14 (%rdx)
+       mov %r13, SEV_ES_R13 (%rdx)
+       mov %r12, SEV_ES_R12 (%rdx)
+       mov %rbx, SEV_ES_RBX (%rdx)
 
-       /* Accessed directly from the stack in RESTORE_HOST_SPEC_CTRL.  */
-       push %_ASM_ARG2
-
-       /* Save @svm. */
-       push %_ASM_ARG1
-
-.ifnc _ASM_ARG1, _ASM_DI
        /*
-        * Stash @svm in RDI early. On 32-bit, arguments are in RAX, RCX
-        * and RDX which are clobbered by RESTORE_GUEST_SPEC_CTRL.
+        * Save volatile registers that hold arguments that are needed after
+        * #VMEXIT (RDI=@svm and RSI=@spec_ctrl_intercepted).
         */
-       mov %_ASM_ARG1, %_ASM_DI
-.endif
+       mov %rdi, SEV_ES_RDI (%rdx)
+       mov %rsi, SEV_ES_RSI (%rdx)
 
-       /* Clobbers RAX, RCX, RDX */
+       /* Clobbers RAX, RCX, RDX (@hostsa). */
        RESTORE_GUEST_SPEC_CTRL
 
        /* Get svm->current_vmcb->pa into RAX. */
-       mov SVM_current_vmcb(%_ASM_DI), %_ASM_AX
-       mov KVM_VMCB_pa(%_ASM_AX), %_ASM_AX
+       mov SVM_current_vmcb(%rdi), %rax
+       mov KVM_VMCB_pa(%rax), %rax
 
        /* Enter guest mode */
        sti
 
-1:     vmrun %_ASM_AX
+1:     vmrun %rax
 
 2:     cli
 
-       /* Pop @svm to RDI, guest registers have been saved already. */
-       pop %_ASM_DI
-
 #ifdef CONFIG_MITIGATION_RETPOLINE
        /* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
-       FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
+       FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
 #endif
 
-       /* Clobbers RAX, RCX, RDX */
+       /* Clobbers RAX, RCX, RDX, consumes RDI (@svm) and RSI (@spec_ctrl_intercepted). */
        RESTORE_HOST_SPEC_CTRL
 
        /*
@@ -361,30 +365,17 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run)
         */
        UNTRAIN_RET_VM
 
-       /* "Pop" @spec_ctrl_intercepted.  */
-       pop %_ASM_BX
-
-       pop %_ASM_BX
-
-#ifdef CONFIG_X86_64
-       pop %r12
-       pop %r13
-       pop %r14
-       pop %r15
-#else
-       pop %esi
-       pop %edi
-#endif
-       pop %_ASM_BP
+       FRAME_END
        RET
 
        RESTORE_GUEST_SPEC_CTRL_BODY
-       RESTORE_HOST_SPEC_CTRL_BODY
+       RESTORE_HOST_SPEC_CTRL_BODY %sil
 
-3:     cmpb $0, _ASM_RIP(kvm_rebooting)
+3:     cmpb $0, kvm_rebooting(%rip)
        jne 2b
        ud2
 
        _ASM_EXTABLE(1b, 3b)
 
 SYM_FUNC_END(__svm_sev_es_vcpu_run)
+#endif /* CONFIG_KVM_AMD_SEV */
index 12ade343a17ed5c7aaa2efc1ebf3b3b40046d907..be40474de6e4dbd28379780c075385a79ed776d2 100644 (file)
@@ -535,7 +535,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
        perf_capabilities = vcpu_get_perf_capabilities(vcpu);
        if (cpuid_model_is_consistent(vcpu) &&
            (perf_capabilities & PMU_CAP_LBR_FMT))
-               x86_perf_get_lbr(&lbr_desc->records);
+               memcpy(&lbr_desc->records, &vmx_lbr_caps, sizeof(vmx_lbr_caps));
        else
                lbr_desc->records.nr = 0;
 
index c37a89eda90f8219de02c96452a5cdbe5d13da83..22411f4aff5303db5b27ee737ba1565f91585bd1 100644 (file)
@@ -218,6 +218,8 @@ module_param(ple_window_max, uint, 0444);
 int __read_mostly pt_mode = PT_MODE_SYSTEM;
 module_param(pt_mode, int, S_IRUGO);
 
+struct x86_pmu_lbr __ro_after_init vmx_lbr_caps;
+
 static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush);
 static DEFINE_STATIC_KEY_FALSE(vmx_l1d_flush_cond);
 static DEFINE_MUTEX(vmx_l1d_flush_mutex);
@@ -7862,10 +7864,9 @@ static void vmx_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
        vmx_update_exception_bitmap(vcpu);
 }
 
-static u64 vmx_get_perf_capabilities(void)
+static __init u64 vmx_get_perf_capabilities(void)
 {
        u64 perf_cap = PMU_CAP_FW_WRITES;
-       struct x86_pmu_lbr lbr;
        u64 host_perf_cap = 0;
 
        if (!enable_pmu)
@@ -7875,15 +7876,43 @@ static u64 vmx_get_perf_capabilities(void)
                rdmsrl(MSR_IA32_PERF_CAPABILITIES, host_perf_cap);
 
        if (!cpu_feature_enabled(X86_FEATURE_ARCH_LBR)) {
-               x86_perf_get_lbr(&lbr);
-               if (lbr.nr)
+               x86_perf_get_lbr(&vmx_lbr_caps);
+
+               /*
+                * KVM requires LBR callstack support, as the overhead due to
+                * context switching LBRs without said support is too high.
+                * See intel_pmu_create_guest_lbr_event() for more info.
+                */
+               if (!vmx_lbr_caps.has_callstack)
+                       memset(&vmx_lbr_caps, 0, sizeof(vmx_lbr_caps));
+               else if (vmx_lbr_caps.nr)
                        perf_cap |= host_perf_cap & PMU_CAP_LBR_FMT;
        }
 
        if (vmx_pebs_supported()) {
                perf_cap |= host_perf_cap & PERF_CAP_PEBS_MASK;
-               if ((perf_cap & PERF_CAP_PEBS_FORMAT) < 4)
-                       perf_cap &= ~PERF_CAP_PEBS_BASELINE;
+
+               /*
+                * Disallow adaptive PEBS as it is functionally broken, can be
+                * used by the guest to read *host* LBRs, and can be used to
+                * bypass userspace event filters.  To correctly and safely
+                * support adaptive PEBS, KVM needs to:
+                *
+                * 1. Account for the ADAPTIVE flag when (re)programming fixed
+                *    counters.
+                *
+                * 2. Gain support from perf (or take direct control of counter
+                *    programming) to support events without adaptive PEBS
+                *    enabled for the hardware counter.
+                *
+                * 3. Ensure LBR MSRs cannot hold host data on VM-Entry with
+                *    adaptive PEBS enabled and MSR_PEBS_DATA_CFG.LBRS=1.
+                *
+                * 4. Document which PMU events are effectively exposed to the
+                *    guest via adaptive PEBS, and make adaptive PEBS mutually
+                *    exclusive with KVM_SET_PMU_EVENT_FILTER if necessary.
+                */
+               perf_cap &= ~PERF_CAP_PEBS_BASELINE;
        }
 
        return perf_cap;
index 65786dbe7d60bdf753db779312bb70754ccc6f1e..90f9e443464645507ba767d246290e13079fa397 100644 (file)
@@ -15,6 +15,7 @@
 #include "vmx_ops.h"
 #include "../cpuid.h"
 #include "run_flags.h"
+#include "../mmu.h"
 
 #define MSR_TYPE_R     1
 #define MSR_TYPE_W     2
@@ -109,6 +110,8 @@ struct lbr_desc {
        bool msr_passthrough;
 };
 
+extern struct x86_pmu_lbr vmx_lbr_caps;
+
 /*
  * The nested_vmx structure is part of vcpu_vmx, and holds information we need
  * for correct emulation of VMX (i.e., nested VMX) on this vcpu.
@@ -719,7 +722,8 @@ static inline bool vmx_need_pf_intercept(struct kvm_vcpu *vcpu)
        if (!enable_ept)
                return true;
 
-       return allow_smaller_maxphyaddr && cpuid_maxphyaddr(vcpu) < boot_cpu_data.x86_phys_bits;
+       return allow_smaller_maxphyaddr &&
+              cpuid_maxphyaddr(vcpu) < kvm_get_shadow_phys_bits();
 }
 
 static inline bool is_unrestricted_guest(struct kvm_vcpu *vcpu)
index 984ea2089efc3132154527508976879a4e11cb10..91478b769af0896cd8bdb8db9bc0ff0861a8d6f5 100644 (file)
@@ -3470,7 +3470,7 @@ static bool is_mci_status_msr(u32 msr)
 static bool can_set_mci_status(struct kvm_vcpu *vcpu)
 {
        /* McStatusWrEn enabled? */
-       if (guest_cpuid_is_amd_or_hygon(vcpu))
+       if (guest_cpuid_is_amd_compatible(vcpu))
                return !!(vcpu->arch.msr_hwcr & BIT_ULL(18));
 
        return false;
index e674ccf720b9f6befe6ffb0fccec192fb1aa9a89..391059b2c6fbc4a571f0582c7c4654147a930cef 100644 (file)
@@ -382,8 +382,15 @@ SYM_FUNC_END(call_depth_return_thunk)
 SYM_CODE_START(__x86_return_thunk)
        UNWIND_HINT_FUNC
        ANNOTATE_NOENDBR
+#if defined(CONFIG_MITIGATION_UNRET_ENTRY) || \
+    defined(CONFIG_MITIGATION_SRSO) || \
+    defined(CONFIG_MITIGATION_CALL_DEPTH_TRACKING)
        ALTERNATIVE __stringify(ANNOTATE_UNRET_SAFE; ret), \
                   "jmp warn_thunk_thunk", X86_FEATURE_ALWAYS
+#else
+       ANNOTATE_UNRET_SAFE
+       ret
+#endif
        int3
 SYM_CODE_END(__x86_return_thunk)
 EXPORT_SYMBOL(__x86_return_thunk)
index 622d12ec7f08518ba6701c33efd74d5f77545806..bba4e020dd646cc257056fa05ece3ccdc24ae560 100644 (file)
@@ -723,39 +723,8 @@ kernelmode_fixup_or_oops(struct pt_regs *regs, unsigned long error_code,
        WARN_ON_ONCE(user_mode(regs));
 
        /* Are we prepared to handle this kernel fault? */
-       if (fixup_exception(regs, X86_TRAP_PF, error_code, address)) {
-               /*
-                * Any interrupt that takes a fault gets the fixup. This makes
-                * the below recursive fault logic only apply to a faults from
-                * task context.
-                */
-               if (in_interrupt())
-                       return;
-
-               /*
-                * Per the above we're !in_interrupt(), aka. task context.
-                *
-                * In this case we need to make sure we're not recursively
-                * faulting through the emulate_vsyscall() logic.
-                */
-               if (current->thread.sig_on_uaccess_err && signal) {
-                       sanitize_error_code(address, &error_code);
-
-                       set_signal_archinfo(address, error_code);
-
-                       if (si_code == SEGV_PKUERR) {
-                               force_sig_pkuerr((void __user *)address, pkey);
-                       } else {
-                               /* XXX: hwpoison faults will set the wrong code. */
-                               force_sig_fault(signal, si_code, (void __user *)address);
-                       }
-               }
-
-               /*
-                * Barring that, we can do the fixup and be happy.
-                */
+       if (fixup_exception(regs, X86_TRAP_PF, error_code, address))
                return;
-       }
 
        /*
         * AMD erratum #91 manifests as a spurious page fault on a PREFETCH
index 6f3b3e028718556667c1d86e8f56442eafc78dcc..0a120d85d7bba88b33c59b97f9109a6acde727cd 100644 (file)
@@ -102,6 +102,13 @@ void __init mem_encrypt_setup_arch(void)
        phys_addr_t total_mem = memblock_phys_mem_size();
        unsigned long size;
 
+       /*
+        * Do RMP table fixups after the e820 tables have been setup by
+        * e820__memory_setup().
+        */
+       if (cc_platform_has(CC_ATTR_HOST_SEV_SNP))
+               snp_fixup_e820_tables();
+
        if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
                return;
 
index df5fac428408fe65ecc03766def03e0959bc539a..59cbc94b6e6903d915d9b16b04e82f269c88754b 100644 (file)
@@ -1807,36 +1807,41 @@ populate_extable:
                        if (BPF_MODE(insn->code) == BPF_PROBE_MEM ||
                            BPF_MODE(insn->code) == BPF_PROBE_MEMSX) {
                                /* Conservatively check that src_reg + insn->off is a kernel address:
-                                *   src_reg + insn->off >= TASK_SIZE_MAX + PAGE_SIZE
-                                * src_reg is used as scratch for src_reg += insn->off and restored
-                                * after emit_ldx if necessary
+                                *   src_reg + insn->off > TASK_SIZE_MAX + PAGE_SIZE
+                                *   and
+                                *   src_reg + insn->off < VSYSCALL_ADDR
                                 */
 
-                               u64 limit = TASK_SIZE_MAX + PAGE_SIZE;
+                               u64 limit = TASK_SIZE_MAX + PAGE_SIZE - VSYSCALL_ADDR;
                                u8 *end_of_jmp;
 
-                               /* At end of these emitted checks, insn->off will have been added
-                                * to src_reg, so no need to do relative load with insn->off offset
-                                */
-                               insn_off = 0;
+                               /* movabsq r10, VSYSCALL_ADDR */
+                               emit_mov_imm64(&prog, BPF_REG_AX, (long)VSYSCALL_ADDR >> 32,
+                                              (u32)(long)VSYSCALL_ADDR);
 
-                               /* movabsq r11, limit */
-                               EMIT2(add_1mod(0x48, AUX_REG), add_1reg(0xB8, AUX_REG));
-                               EMIT((u32)limit, 4);
-                               EMIT(limit >> 32, 4);
+                               /* mov src_reg, r11 */
+                               EMIT_mov(AUX_REG, src_reg);
 
                                if (insn->off) {
-                                       /* add src_reg, insn->off */
-                                       maybe_emit_1mod(&prog, src_reg, true);
-                                       EMIT2_off32(0x81, add_1reg(0xC0, src_reg), insn->off);
+                                       /* add r11, insn->off */
+                                       maybe_emit_1mod(&prog, AUX_REG, true);
+                                       EMIT2_off32(0x81, add_1reg(0xC0, AUX_REG), insn->off);
                                }
 
-                               /* cmp src_reg, r11 */
-                               maybe_emit_mod(&prog, src_reg, AUX_REG, true);
-                               EMIT2(0x39, add_2reg(0xC0, src_reg, AUX_REG));
+                               /* sub r11, r10 */
+                               maybe_emit_mod(&prog, AUX_REG, BPF_REG_AX, true);
+                               EMIT2(0x29, add_2reg(0xC0, AUX_REG, BPF_REG_AX));
+
+                               /* movabsq r10, limit */
+                               emit_mov_imm64(&prog, BPF_REG_AX, (long)limit >> 32,
+                                              (u32)(long)limit);
+
+                               /* cmp r10, r11 */
+                               maybe_emit_mod(&prog, AUX_REG, BPF_REG_AX, true);
+                               EMIT2(0x39, add_2reg(0xC0, AUX_REG, BPF_REG_AX));
 
-                               /* if unsigned '>=', goto load */
-                               EMIT2(X86_JAE, 0);
+                               /* if unsigned '>', goto load */
+                               EMIT2(X86_JA, 0);
                                end_of_jmp = prog;
 
                                /* xor dst_reg, dst_reg */
@@ -1862,18 +1867,6 @@ populate_extable:
                                /* populate jmp_offset for JMP above */
                                start_of_ldx[-1] = prog - start_of_ldx;
 
-                               if (insn->off && src_reg != dst_reg) {
-                                       /* sub src_reg, insn->off
-                                        * Restore src_reg after "add src_reg, insn->off" in prev
-                                        * if statement. But if src_reg == dst_reg, emit_ldx
-                                        * above already clobbered src_reg, so no need to restore.
-                                        * If add src_reg, insn->off was unnecessary, no need to
-                                        * restore either.
-                                        */
-                                       maybe_emit_1mod(&prog, src_reg, true);
-                                       EMIT2_off32(0x81, add_1reg(0xE8, src_reg), insn->off);
-                               }
-
                                if (!bpf_prog->aux->extable)
                                        break;
 
@@ -3473,3 +3466,9 @@ bool bpf_jit_supports_ptr_xchg(void)
 {
        return true;
 }
+
+/* x86-64 JIT emits its own code to filter user addresses so return 0 here */
+u64 bpf_arch_uaddress_limit(void)
+{
+       return 0;
+}
index ab0e8448bb6eb2bfbc4fab29321cd0ddbe876f7e..0ae10535c699982e15f20026a3e8012e52c41f32 100644 (file)
@@ -163,6 +163,42 @@ bool snp_probe_rmptable_info(void)
        return true;
 }
 
+static void __init __snp_fixup_e820_tables(u64 pa)
+{
+       if (IS_ALIGNED(pa, PMD_SIZE))
+               return;
+
+       /*
+        * Handle cases where the RMP table placement by the BIOS is not
+        * 2M aligned and the kexec kernel could try to allocate
+        * from within that chunk which then causes a fatal RMP fault.
+        *
+        * The e820_table needs to be updated as it is converted to
+        * kernel memory resources and used by KEXEC_FILE_LOAD syscall
+        * to load kexec segments.
+        *
+        * The e820_table_firmware needs to be updated as it is exposed
+        * to sysfs and used by the KEXEC_LOAD syscall to load kexec
+        * segments.
+        *
+        * The e820_table_kexec needs to be updated as it passed to
+        * the kexec-ed kernel.
+        */
+       pa = ALIGN_DOWN(pa, PMD_SIZE);
+       if (e820__mapped_any(pa, pa + PMD_SIZE, E820_TYPE_RAM)) {
+               pr_info("Reserving start/end of RMP table on a 2MB boundary [0x%016llx]\n", pa);
+               e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+               e820__range_update_table(e820_table_kexec, pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+               e820__range_update_table(e820_table_firmware, pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+       }
+}
+
+void __init snp_fixup_e820_tables(void)
+{
+       __snp_fixup_e820_tables(probed_rmp_base);
+       __snp_fixup_e820_tables(probed_rmp_base + probed_rmp_size);
+}
+
 /*
  * Do the necessary preparations which are verified by the firmware as
  * described in the SNP_INIT_EX firmware command description in the SNP
index ace2eb054053f95e53ac43992d9b778335e68748..9ba53814ed6a9e392b60c53477246977d649f20e 100644 (file)
@@ -219,13 +219,21 @@ static __read_mostly unsigned int cpuid_leaf5_edx_val;
 static void xen_cpuid(unsigned int *ax, unsigned int *bx,
                      unsigned int *cx, unsigned int *dx)
 {
-       unsigned maskebx = ~0;
+       unsigned int maskebx = ~0;
+       unsigned int or_ebx = 0;
 
        /*
         * Mask out inconvenient features, to try and disable as many
         * unsupported kernel subsystems as possible.
         */
        switch (*ax) {
+       case 0x1:
+               /* Replace initial APIC ID in bits 24-31 of EBX. */
+               /* See xen_pv_smp_config() for related topology preparations. */
+               maskebx = 0x00ffffff;
+               or_ebx = smp_processor_id() << 24;
+               break;
+
        case CPUID_MWAIT_LEAF:
                /* Synthesize the values.. */
                *ax = 0;
@@ -248,6 +256,7 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
                : "0" (*ax), "2" (*cx));
 
        *bx &= maskebx;
+       *bx |= or_ebx;
 }
 
 static bool __init xen_check_mwait(void)
index 27d1a5b7f571a3487cfa68a037e51516a6b9b287..ac41d83b38d3c49d3116dff58d5998a5fe9efb62 100644 (file)
@@ -154,9 +154,9 @@ static void __init xen_pv_smp_config(void)
        u32 apicid = 0;
        int i;
 
-       topology_register_boot_apic(apicid++);
+       topology_register_boot_apic(apicid);
 
-       for (i = 1; i < nr_cpu_ids; i++)
+       for (i = 0; i < nr_cpu_ids; i++)
                topology_register_apic(apicid++, CPU_ACPIID_INVALID, true);
 
        /* Pretend to be a proper enumerated system */
index 38bcecb0e457d9741c142cada4d38ec65ff0f88b..a2b6bb5429f5cb4c3c9694c9db6dbb8f6992d9fa 100644 (file)
@@ -100,6 +100,10 @@ void flush_cache_range(struct vm_area_struct*, ulong, ulong);
 void flush_icache_range(unsigned long start, unsigned long end);
 void flush_cache_page(struct vm_area_struct*,
                             unsigned long, unsigned long);
+#define flush_cache_all flush_cache_all
+#define flush_cache_range flush_cache_range
+#define flush_icache_range flush_icache_range
+#define flush_cache_page flush_cache_page
 #else
 #define flush_cache_all local_flush_cache_all
 #define flush_cache_range local_flush_cache_range
@@ -136,20 +140,7 @@ void local_flush_cache_page(struct vm_area_struct *vma,
 
 #else
 
-#define flush_cache_all()                              do { } while (0)
-#define flush_cache_mm(mm)                             do { } while (0)
-#define flush_cache_dup_mm(mm)                         do { } while (0)
-
-#define flush_cache_vmap(start,end)                    do { } while (0)
-#define flush_cache_vmap_early(start,end)              do { } while (0)
-#define flush_cache_vunmap(start,end)                  do { } while (0)
-
-#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
-#define flush_dcache_page(page)                                do { } while (0)
-
 #define flush_icache_range local_flush_icache_range
-#define flush_cache_page(vma, addr, pfn)               do { } while (0)
-#define flush_cache_range(vma, start, end)             do { } while (0)
 
 #endif
 
@@ -162,15 +153,14 @@ void local_flush_cache_page(struct vm_area_struct *vma,
                __invalidate_icache_range(start,(end) - (start));       \
        } while (0)
 
-#define flush_dcache_mmap_lock(mapping)                        do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)              do { } while (0)
-
 #if defined(CONFIG_MMU) && (DCACHE_WAY_SIZE > PAGE_SIZE)
 
 extern void copy_to_user_page(struct vm_area_struct*, struct page*,
                unsigned long, void*, const void*, unsigned long);
 extern void copy_from_user_page(struct vm_area_struct*, struct page*,
                unsigned long, void*, const void*, unsigned long);
+#define copy_to_user_page copy_to_user_page
+#define copy_from_user_page copy_from_user_page
 
 #else
 
@@ -186,4 +176,6 @@ extern void copy_from_user_page(struct vm_area_struct*, struct page*,
 
 #endif
 
+#include <asm-generic/cacheflush.h>
+
 #endif /* _XTENSA_CACHEFLUSH_H */
index d008a153a2b9f7a9782b5874643f2d5a3741e995..7ed1a2085bd72883025c7de7d0d028ab077cc56c 100644 (file)
 #define MAKE_RA_FOR_CALL(ra,ws)   (((ra) & 0x3fffffff) | (ws) << 30)
 
 /* Convert return address to a valid pc
- * Note: We assume that the stack pointer is in the same 1GB ranges as the ra
+ * Note: 'text' is the address within the same 1GB range as the ra
  */
-#define MAKE_PC_FROM_RA(ra,sp)    (((ra) & 0x3fffffff) | ((sp) & 0xc0000000))
+#define MAKE_PC_FROM_RA(ra, text) (((ra) & 0x3fffffff) | ((unsigned long)(text) & 0xc0000000))
 
 #elif defined(__XTENSA_CALL0_ABI__)
 
 #define MAKE_RA_FOR_CALL(ra, ws)   (ra)
 
 /* Convert return address to a valid pc
- * Note: We assume that the stack pointer is in the same 1GB ranges as the ra
+ * Note: 'text' is not used as 'ra' is always the full address
  */
-#define MAKE_PC_FROM_RA(ra, sp)    (ra)
+#define MAKE_PC_FROM_RA(ra, text)  (ra)
 
 #else
 #error Unsupported Xtensa ABI
index a270467556dc84df2c6ceb0786acee3669a059f8..86c70117371bb7cc022b0793f0a4eb8ef834bc63 100644 (file)
@@ -87,7 +87,7 @@ struct pt_regs {
 # define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
 # define instruction_pointer(regs) ((regs)->pc)
 # define return_pointer(regs) (MAKE_PC_FROM_RA((regs)->areg[0], \
-                                              (regs)->areg[1]))
+                                              (regs)->pc))
 
 # ifndef CONFIG_SMP
 #  define profile_pc(regs) instruction_pointer(regs)
index a815577d25fd02f3b267359d923cb83aae512c3d..7bd66677f7b6de58d0a1bda1b414ebc622dce962 100644 (file)
@@ -47,6 +47,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/regs.h>
 #include <asm/hw_breakpoint.h>
+#include <asm/sections.h>
 #include <asm/traps.h>
 
 extern void ret_from_fork(void);
@@ -380,7 +381,7 @@ unsigned long __get_wchan(struct task_struct *p)
        int count = 0;
 
        sp = p->thread.sp;
-       pc = MAKE_PC_FROM_RA(p->thread.ra, p->thread.sp);
+       pc = MAKE_PC_FROM_RA(p->thread.ra, _text);
 
        do {
                if (sp < stack_page + sizeof(struct task_struct) ||
@@ -392,7 +393,7 @@ unsigned long __get_wchan(struct task_struct *p)
 
                /* Stack layout: sp-4: ra, sp-3: sp' */
 
-               pc = MAKE_PC_FROM_RA(SPILL_SLOT(sp, 0), sp);
+               pc = MAKE_PC_FROM_RA(SPILL_SLOT(sp, 0), _text);
                sp = SPILL_SLOT(sp, 1);
        } while (count++ < 16);
        return 0;
index 831ffb648bda7e160408fd97530eddee760c27fc..ed324fdf2a2f9124527a5514ce14ac731996a2ad 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/stacktrace.h>
 
 #include <asm/ftrace.h>
+#include <asm/sections.h>
 #include <asm/stacktrace.h>
 #include <asm/traps.h>
 #include <linux/uaccess.h>
@@ -189,7 +190,7 @@ void walk_stackframe(unsigned long *sp,
                if (a1 <= (unsigned long)sp)
                        break;
 
-               frame.pc = MAKE_PC_FROM_RA(a0, a1);
+               frame.pc = MAKE_PC_FROM_RA(a0, _text);
                frame.sp = a1;
 
                if (fn(&frame, data))
index 8896e691c051eab87ba88ffcbac01bd4860df0de..abec44b687dff0d4da3a77307603a0866a35ce88 100644 (file)
@@ -166,10 +166,8 @@ late_initcall(rs_init);
 
 static void iss_console_write(struct console *co, const char *s, unsigned count)
 {
-       if (s && *s != 0) {
-               int len = strlen(s);
-               simc_write(1, s, count < len ? count : len);
-       }
+       if (s && *s != 0)
+               simc_write(1, s, min(count, strlen(s)));
 }
 
 static struct tty_driver* iss_console_device(struct console *c, int *index)
index b8e32d933a6369aebbffe36e2ce3165cc2288bef..da2a167a4d08b66fe26c99826a9e84277f76f0e3 100644 (file)
@@ -645,6 +645,14 @@ static void blkdev_flush_mapping(struct block_device *bdev)
        bdev_write_inode(bdev);
 }
 
+static void blkdev_put_whole(struct block_device *bdev)
+{
+       if (atomic_dec_and_test(&bdev->bd_openers))
+               blkdev_flush_mapping(bdev);
+       if (bdev->bd_disk->fops->release)
+               bdev->bd_disk->fops->release(bdev->bd_disk);
+}
+
 static int blkdev_get_whole(struct block_device *bdev, blk_mode_t mode)
 {
        struct gendisk *disk = bdev->bd_disk;
@@ -663,20 +671,21 @@ static int blkdev_get_whole(struct block_device *bdev, blk_mode_t mode)
 
        if (!atomic_read(&bdev->bd_openers))
                set_init_blocksize(bdev);
-       if (test_bit(GD_NEED_PART_SCAN, &disk->state))
-               bdev_disk_changed(disk, false);
        atomic_inc(&bdev->bd_openers);
+       if (test_bit(GD_NEED_PART_SCAN, &disk->state)) {
+               /*
+                * Only return scanning errors if we are called from contexts
+                * that explicitly want them, e.g. the BLKRRPART ioctl.
+                */
+               ret = bdev_disk_changed(disk, false);
+               if (ret && (mode & BLK_OPEN_STRICT_SCAN)) {
+                       blkdev_put_whole(bdev);
+                       return ret;
+               }
+       }
        return 0;
 }
 
-static void blkdev_put_whole(struct block_device *bdev)
-{
-       if (atomic_dec_and_test(&bdev->bd_openers))
-               blkdev_flush_mapping(bdev);
-       if (bdev->bd_disk->fops->release)
-               bdev->bd_disk->fops->release(bdev->bd_disk);
-}
-
 static int blkdev_get_part(struct block_device *part, blk_mode_t mode)
 {
        struct gendisk *disk = part->bd_disk;
@@ -873,7 +882,7 @@ int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder,
                goto abort_claiming;
        ret = -EBUSY;
        if (!bdev_may_open(bdev, mode))
-               goto abort_claiming;
+               goto put_module;
        if (bdev_is_partition(bdev))
                ret = blkdev_get_part(bdev, mode);
        else
index baa20c85799d54a86df05aa412c2e38849a800b4..690ca99dfaca6772a2b17142aacd52d4c49fe673 100644 (file)
@@ -1439,8 +1439,11 @@ static void iocg_pay_debt(struct ioc_gq *iocg, u64 abs_vpay,
        lockdep_assert_held(&iocg->ioc->lock);
        lockdep_assert_held(&iocg->waitq.lock);
 
-       /* make sure that nobody messed with @iocg */
-       WARN_ON_ONCE(list_empty(&iocg->active_list));
+       /*
+        * make sure that nobody messed with @iocg. Check iocg->pd.online
+        * to avoid warn when removing blkcg or disk.
+        */
+       WARN_ON_ONCE(list_empty(&iocg->active_list) && iocg->pd.online);
        WARN_ON_ONCE(iocg->inuse > 1);
 
        iocg->abs_vdebt -= min(abs_vpay, iocg->abs_vdebt);
index a9028a2c2db57b0881b7faf7cee2243148d1626c..f505f9c341eb08bd57bbcb729f603b5ac48453f0 100644 (file)
@@ -563,7 +563,8 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
                        return -EACCES;
                if (bdev_is_partition(bdev))
                        return -EINVAL;
-               return disk_scan_partitions(bdev->bd_disk, mode);
+               return disk_scan_partitions(bdev->bd_disk,
+                               mode | BLK_OPEN_STRICT_SCAN);
        case BLKTRACESTART:
        case BLKTRACESTOP:
        case BLKTRACETEARDOWN:
index 1fbc9b921c4fccbff6bb64981ce678efd1841890..736c2eb8c0f37d58529ea500c33b8167ad9d248e 100644 (file)
@@ -574,7 +574,7 @@ static u_long get_word(struct vc_data *vc)
        }
        attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr);
        buf[cnt++] = attr_ch;
-       while (tmpx < vc->vc_cols - 1) {
+       while (tmpx < vc->vc_cols - 1 && cnt < sizeof(buf) - 1) {
                tmp_pos += 2;
                tmpx++;
                ch = get_char(vc, (u_short *)tmp_pos, &temp);
index 4bfbe55553f410119378fc3bbf8c73b9d6717a05..1d857978f5f40753f0bafd591123b0db588df8da 100644 (file)
@@ -170,8 +170,8 @@ show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, wraparound_time);
 #define GET_BIT_WIDTH(reg) ((reg)->access_width ? (8 << ((reg)->access_width - 1)) : (reg)->bit_width)
 
 /* Shift and apply the mask for CPC reads/writes */
-#define MASK_VAL(reg, val) ((val) >> ((reg)->bit_offset &                      \
-                                       GENMASK(((reg)->bit_width), 0)))
+#define MASK_VAL(reg, val) (((val) >> (reg)->bit_offset) &                     \
+                                       GENMASK(((reg)->bit_width) - 1, 0))
 
 static ssize_t show_feedback_ctrs(struct kobject *kobj,
                struct kobj_attribute *attr, char *buf)
@@ -686,8 +686,10 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
 
        if (!osc_sb_cppc2_support_acked) {
                pr_debug("CPPC v2 _OSC not acked\n");
-               if (!cpc_supported_by_cpu())
+               if (!cpc_supported_by_cpu()) {
+                       pr_debug("CPPC is not supported by the CPU\n");
                        return -ENODEV;
+               }
        }
 
        /* Parse the ACPI _CPC table for this CPU. */
@@ -1002,14 +1004,14 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
        }
 
        *val = 0;
+       size = GET_BIT_WIDTH(reg);
 
        if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
-               u32 width = GET_BIT_WIDTH(reg);
                u32 val_u32;
                acpi_status status;
 
                status = acpi_os_read_port((acpi_io_address)reg->address,
-                                          &val_u32, width);
+                                          &val_u32, size);
                if (ACPI_FAILURE(status)) {
                        pr_debug("Error: Failed to read SystemIO port %llx\n",
                                 reg->address);
@@ -1018,17 +1020,22 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
 
                *val = val_u32;
                return 0;
-       } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
+       } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) {
+               /*
+                * For registers in PCC space, the register size is determined
+                * by the bit width field; the access size is used to indicate
+                * the PCC subspace id.
+                */
+               size = reg->bit_width;
                vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
+       }
        else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
                vaddr = reg_res->sys_mem_vaddr;
        else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE)
                return cpc_read_ffh(cpu, reg, val);
        else
                return acpi_os_read_memory((acpi_physical_address)reg->address,
-                               val, reg->bit_width);
-
-       size = GET_BIT_WIDTH(reg);
+                               val, size);
 
        switch (size) {
        case 8:
@@ -1044,8 +1051,13 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
                *val = readq_relaxed(vaddr);
                break;
        default:
-               pr_debug("Error: Cannot read %u bit width from PCC for ss: %d\n",
-                        reg->bit_width, pcc_ss_id);
+               if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
+                       pr_debug("Error: Cannot read %u bit width from system memory: 0x%llx\n",
+                               size, reg->address);
+               } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
+                       pr_debug("Error: Cannot read %u bit width from PCC for ss: %d\n",
+                               size, pcc_ss_id);
+               }
                return -EFAULT;
        }
 
@@ -1063,12 +1075,13 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
        int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
        struct cpc_reg *reg = &reg_res->cpc_entry.reg;
 
+       size = GET_BIT_WIDTH(reg);
+
        if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
-               u32 width = GET_BIT_WIDTH(reg);
                acpi_status status;
 
                status = acpi_os_write_port((acpi_io_address)reg->address,
-                                           (u32)val, width);
+                                           (u32)val, size);
                if (ACPI_FAILURE(status)) {
                        pr_debug("Error: Failed to write SystemIO port %llx\n",
                                 reg->address);
@@ -1076,17 +1089,22 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
                }
 
                return 0;
-       } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
+       } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) {
+               /*
+                * For registers in PCC space, the register size is determined
+                * by the bit width field; the access size is used to indicate
+                * the PCC subspace id.
+                */
+               size = reg->bit_width;
                vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
+       }
        else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
                vaddr = reg_res->sys_mem_vaddr;
        else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE)
                return cpc_write_ffh(cpu, reg, val);
        else
                return acpi_os_write_memory((acpi_physical_address)reg->address,
-                               val, reg->bit_width);
-
-       size = GET_BIT_WIDTH(reg);
+                               val, size);
 
        if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
                val = MASK_VAL(reg, val);
@@ -1105,8 +1123,13 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
                writeq_relaxed(val, vaddr);
                break;
        default:
-               pr_debug("Error: Cannot write %u bit width to PCC for ss: %d\n",
-                        reg->bit_width, pcc_ss_id);
+               if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
+                       pr_debug("Error: Cannot write %u bit width to system memory: 0x%llx\n",
+                               size, reg->address);
+               } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
+                       pr_debug("Error: Cannot write %u bit width to PCC for ss: %d\n",
+                               size, pcc_ss_id);
+               }
                ret_val = -EFAULT;
                break;
        }
index cd84af23f7eac8fad793c6393bcd8130596077ce..dd0b40b9bbe8bef5f8c30a082eebbc25dcdfeafd 100644 (file)
@@ -492,16 +492,14 @@ static int lps0_device_attach(struct acpi_device *adev,
                        unsigned int func_mask;
 
                        /*
-                        * Avoid evaluating the same _DSM function for two
-                        * different UUIDs and prioritize the MSFT one.
+                        * Log a message if the _DSM function sets for two
+                        * different UUIDs overlap.
                         */
                        func_mask = lps0_dsm_func_mask & lps0_dsm_func_mask_microsoft;
-                       if (func_mask) {
+                       if (func_mask)
                                acpi_handle_info(adev->handle,
                                                 "Duplicate LPS0 _DSM functions (mask: 0x%x)\n",
                                                 func_mask);
-                               lps0_dsm_func_mask &= ~func_mask;
-                       }
                }
        }
 
index bad28cf42010415bee522cb2f778bd866a756584..dd6923d37931f9565dac0a112458a885568a4253 100644 (file)
@@ -1708,8 +1708,10 @@ static size_t binder_get_object(struct binder_proc *proc,
        size_t object_size = 0;
 
        read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
-       if (offset > buffer->data_size || read_size < sizeof(*hdr))
+       if (offset > buffer->data_size || read_size < sizeof(*hdr) ||
+           !IS_ALIGNED(offset, sizeof(u32)))
                return 0;
+
        if (u) {
                if (copy_from_user(object, u + offset, read_size))
                        return 0;
index 5679f966f676d55fa4ef7c3286750298c7c0c3d4..4a67e83300e164cfcaf216004df3786de3597369 100644 (file)
@@ -208,7 +208,7 @@ static ktime_t initcall_debug_start(struct device *dev, void *cb)
        if (!pm_print_times_enabled)
                return 0;
 
-       dev_info(dev, "calling %pS @ %i, parent: %s\n", cb,
+       dev_info(dev, "calling %ps @ %i, parent: %s\n", cb,
                 task_pid_nr(current),
                 dev->parent ? dev_name(dev->parent) : "none");
        return ktime_get();
@@ -223,7 +223,7 @@ static void initcall_debug_report(struct device *dev, ktime_t calltime,
                return;
 
        rettime = ktime_get();
-       dev_info(dev, "%pS returned %d after %Ld usecs\n", cb, error,
+       dev_info(dev, "%ps returned %d after %Ld usecs\n", cb, error,
                 (unsigned long long)ktime_us_delta(rettime, calltime));
 }
 
@@ -1927,7 +1927,7 @@ EXPORT_SYMBOL_GPL(dpm_suspend_start);
 void __suspend_report_result(const char *function, struct device *dev, void *fn, int ret)
 {
        if (ret)
-               dev_err(dev, "%s(): %pS returns %d\n", function, fn, ret);
+               dev_err(dev, "%s(): %ps returns %d\n", function, fn, ret);
 }
 EXPORT_SYMBOL_GPL(__suspend_report_result);
 
index a917219feea62d256a80166879bc01098eee54a3..752b417e81290eb97d578de7f388b83201e52421 100644 (file)
@@ -451,16 +451,15 @@ static struct wakeup_source *device_wakeup_detach(struct device *dev)
  * Detach the @dev's wakeup source object from it, unregister this wakeup source
  * object and destroy it.
  */
-int device_wakeup_disable(struct device *dev)
+void device_wakeup_disable(struct device *dev)
 {
        struct wakeup_source *ws;
 
        if (!dev || !dev->power.can_wakeup)
-               return -EINVAL;
+               return;
 
        ws = device_wakeup_detach(dev);
        wakeup_source_unregister(ws);
-       return 0;
 }
 EXPORT_SYMBOL_GPL(device_wakeup_disable);
 
@@ -502,7 +501,11 @@ EXPORT_SYMBOL_GPL(device_set_wakeup_capable);
  */
 int device_set_wakeup_enable(struct device *dev, bool enable)
 {
-       return enable ? device_wakeup_enable(dev) : device_wakeup_disable(dev);
+       if (enable)
+               return device_wakeup_enable(dev);
+
+       device_wakeup_disable(dev);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(device_set_wakeup_enable);
 
index 5cb425f6f02d4bd1e4aa4f0e58d846a52896fdca..0a34dd3c4f38d298b8766065026cc465801f7aa7 100644 (file)
@@ -2838,6 +2838,43 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
 }
 EXPORT_SYMBOL_GPL(regmap_read);
 
+/**
+ * regmap_read_bypassed() - Read a value from a single register direct
+ *                         from the device, bypassing the cache
+ *
+ * @map: Register map to read from
+ * @reg: Register to be read from
+ * @val: Pointer to store read value
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_read_bypassed(struct regmap *map, unsigned int reg, unsigned int *val)
+{
+       int ret;
+       bool bypass, cache_only;
+
+       if (!IS_ALIGNED(reg, map->reg_stride))
+               return -EINVAL;
+
+       map->lock(map->lock_arg);
+
+       bypass = map->cache_bypass;
+       cache_only = map->cache_only;
+       map->cache_bypass = true;
+       map->cache_only = false;
+
+       ret = _regmap_read(map, reg, val);
+
+       map->cache_bypass = bypass;
+       map->cache_only = cache_only;
+
+       map->unlock(map->lock_arg);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_read_bypassed);
+
 /**
  * regmap_raw_read() - Read raw data from the device
  *
index bea3d5cf8a83487909270d5f2398267250507a31..374e4efa8759fba62df2cdbbc49c9428ddb5ea5b 100644 (file)
@@ -2177,7 +2177,8 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd)
                .max_hw_sectors         = p->max_sectors,
                .chunk_sectors          = p->chunk_sectors,
                .virt_boundary_mask     = p->virt_boundary_mask,
-
+               .max_segments           = USHRT_MAX,
+               .max_segment_size       = UINT_MAX,
        };
        struct gendisk *disk;
        int ret = -EINVAL;
index ac8ebccd350756747eee3400596e04fcbac3cabd..812fd2a8f853e1dc305fa6aab04db8098ea28872 100644 (file)
@@ -380,8 +380,10 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
        switch (data->cd_info.state) {
        case HCI_DEVCOREDUMP_IDLE:
                err = hci_devcd_init(hdev, MTK_COREDUMP_SIZE);
-               if (err < 0)
+               if (err < 0) {
+                       kfree_skb(skb);
                        break;
+               }
                data->cd_info.cnt = 0;
 
                /* It is supposed coredump can be done within 5 seconds */
@@ -407,9 +409,6 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
                break;
        }
 
-       if (err < 0)
-               kfree_skb(skb);
-
        return err;
 }
 EXPORT_SYMBOL_GPL(btmtk_process_coredump);
index 19cfc342fc7bbb67af65cb4de10e074622a991a4..216826c31ee34f0e65ef74edcab98c7cd9eff7e5 100644 (file)
@@ -15,6 +15,8 @@
 
 #define VERSION "0.1"
 
+#define QCA_BDADDR_DEFAULT (&(bdaddr_t) {{ 0xad, 0x5a, 0x00, 0x00, 0x00, 0x00 }})
+
 int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver,
                         enum qca_btsoc_type soc_type)
 {
@@ -612,6 +614,38 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
 }
 EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
 
+static int qca_check_bdaddr(struct hci_dev *hdev)
+{
+       struct hci_rp_read_bd_addr *bda;
+       struct sk_buff *skb;
+       int err;
+
+       if (bacmp(&hdev->public_addr, BDADDR_ANY))
+               return 0;
+
+       skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
+                            HCI_INIT_TIMEOUT);
+       if (IS_ERR(skb)) {
+               err = PTR_ERR(skb);
+               bt_dev_err(hdev, "Failed to read device address (%d)", err);
+               return err;
+       }
+
+       if (skb->len != sizeof(*bda)) {
+               bt_dev_err(hdev, "Device address length mismatch");
+               kfree_skb(skb);
+               return -EIO;
+       }
+
+       bda = (struct hci_rp_read_bd_addr *)skb->data;
+       if (!bacmp(&bda->bdaddr, QCA_BDADDR_DEFAULT))
+               set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
+
+       kfree_skb(skb);
+
+       return 0;
+}
+
 static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size,
                struct qca_btsoc_version ver, u8 rom_ver, u16 bid)
 {
@@ -818,6 +852,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
                break;
        }
 
+       err = qca_check_bdaddr(hdev);
+       if (err)
+               return err;
+
        bt_dev_info(hdev, "QCA setup on UART is completed");
 
        return 0;
index 06e915b57283f8ca3d3ab19b64e1e248e6ecb2bc..e3946f7b736e3cccfe727575096ff073fd86cf1d 100644 (file)
@@ -542,6 +542,8 @@ static const struct usb_device_id quirks_table[] = {
        /* Realtek 8852BE Bluetooth devices */
        { USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK |
                                                     BTUSB_WIDEBAND_SPEECH },
+       { USB_DEVICE(0x0bda, 0x4853), .driver_info = BTUSB_REALTEK |
+                                                    BTUSB_WIDEBAND_SPEECH },
        { USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK |
                                                     BTUSB_WIDEBAND_SPEECH },
        { USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK |
@@ -3480,13 +3482,12 @@ static void btusb_dump_hdr_qca(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void btusb_coredump_qca(struct hci_dev *hdev)
 {
+       int err;
        static const u8 param[] = { 0x26 };
-       struct sk_buff *skb;
 
-       skb = __hci_cmd_sync(hdev, 0xfc0c, 1, param, HCI_CMD_TIMEOUT);
-       if (IS_ERR(skb))
-               bt_dev_err(hdev, "%s: triggle crash failed (%ld)", __func__, PTR_ERR(skb));
-       kfree_skb(skb);
+       err = __hci_cmd_send(hdev, 0xfc0c, 1, param);
+       if (err < 0)
+               bt_dev_err(hdev, "%s: triggle crash failed (%d)", __func__, err);
 }
 
 /*
index ecbc52eaf1010912b9024ddbc3c87aac4254e1e3..0c9c9ee56592dc851ab12f98be5a6be2465b812e 100644 (file)
@@ -1672,6 +1672,9 @@ static bool qca_wakeup(struct hci_dev *hdev)
        struct hci_uart *hu = hci_get_drvdata(hdev);
        bool wakeup;
 
+       if (!hu->serdev)
+               return true;
+
        /* BT SoC attached through the serial bus is handled by the serdev driver.
         * So we need to use the device handle of the serdev driver to get the
         * status of device may wakeup.
@@ -1905,8 +1908,6 @@ retry:
        case QCA_WCN6750:
        case QCA_WCN6855:
        case QCA_WCN7850:
-               set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
-
                qcadev = serdev_device_get_drvdata(hu->serdev);
                if (qcadev->bdaddr_property_broken)
                        set_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks);
@@ -1957,8 +1958,10 @@ retry:
                qca_debugfs_init(hdev);
                hu->hdev->hw_error = qca_hw_error;
                hu->hdev->cmd_timeout = qca_cmd_timeout;
-               if (device_can_wakeup(hu->serdev->ctrl->dev.parent))
-                       hu->hdev->wakeup = qca_wakeup;
+               if (hu->serdev) {
+                       if (device_can_wakeup(hu->serdev->ctrl->dev.parent))
+                               hu->hdev->wakeup = qca_wakeup;
+               }
        } else if (ret == -ENOENT) {
                /* No patch/nvm-config found, run with original fw/config */
                set_bit(QCA_ROM_FW, &qca->flags);
@@ -2329,16 +2332,21 @@ static int qca_serdev_probe(struct serdev_device *serdev)
                    (data->soc_type == QCA_WCN6750 ||
                     data->soc_type == QCA_WCN6855)) {
                        dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n");
-                       power_ctrl_enabled = false;
+                       return PTR_ERR(qcadev->bt_en);
                }
 
+               if (!qcadev->bt_en)
+                       power_ctrl_enabled = false;
+
                qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl",
                                               GPIOD_IN);
                if (IS_ERR(qcadev->sw_ctrl) &&
                    (data->soc_type == QCA_WCN6750 ||
                     data->soc_type == QCA_WCN6855 ||
-                    data->soc_type == QCA_WCN7850))
-                       dev_warn(&serdev->dev, "failed to acquire SW_CTRL gpio\n");
+                    data->soc_type == QCA_WCN7850)) {
+                       dev_err(&serdev->dev, "failed to acquire SW_CTRL gpio\n");
+                       return PTR_ERR(qcadev->sw_ctrl);
+               }
 
                qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL);
                if (IS_ERR(qcadev->susclk)) {
@@ -2357,10 +2365,13 @@ static int qca_serdev_probe(struct serdev_device *serdev)
                qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",
                                               GPIOD_OUT_LOW);
                if (IS_ERR(qcadev->bt_en)) {
-                       dev_warn(&serdev->dev, "failed to acquire enable gpio\n");
-                       power_ctrl_enabled = false;
+                       dev_err(&serdev->dev, "failed to acquire enable gpio\n");
+                       return PTR_ERR(qcadev->bt_en);
                }
 
+               if (!qcadev->bt_en)
+                       power_ctrl_enabled = false;
+
                qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL);
                if (IS_ERR(qcadev->susclk)) {
                        dev_warn(&serdev->dev, "failed to acquire clk\n");
index 456be28ba67cb476846c83c532e7bd04e521463f..2597cb43f43871dc0dc629c13b0b0ee3acf1398a 100644 (file)
@@ -702,7 +702,7 @@ static void extract_entropy(void *buf, size_t len)
 
 static void __cold _credit_init_bits(size_t bits)
 {
-       static struct execute_work set_ready;
+       static DECLARE_WORK(set_ready, crng_set_ready);
        unsigned int new, orig, add;
        unsigned long flags;
 
@@ -718,8 +718,8 @@ static void __cold _credit_init_bits(size_t bits)
 
        if (orig < POOL_READY_BITS && new >= POOL_READY_BITS) {
                crng_reseed(NULL); /* Sets crng_init to CRNG_READY under base_crng.lock. */
-               if (static_key_initialized)
-                       execute_in_process_context(crng_set_ready, &set_ready);
+               if (static_key_initialized && system_unbound_wq)
+                       queue_work(system_unbound_wq, &set_ready);
                atomic_notifier_call_chain(&random_ready_notifier, 0, NULL);
                wake_up_interruptible(&crng_init_wait);
                kill_fasync(&fasync, SIGIO, POLL_IN);
@@ -890,8 +890,8 @@ void __init random_init(void)
 
        /*
         * If we were initialized by the cpu or bootloader before jump labels
-        * are initialized, then we should enable the static branch here, where
-        * it's guaranteed that jump labels have been initialized.
+        * or workqueues are initialized, then we should enable the static
+        * branch here, where it's guaranteed that these have been initialized.
         */
        if (!static_branch_likely(&crng_is_ready) && crng_init >= CRNG_READY)
                crng_set_ready(NULL);
index 25371c91a58fe7cc45a0ae681221d25f801cafb7..8cca52be993f4c831660f0c0d13bac290a37e4de 100644 (file)
@@ -37,6 +37,10 @@ static HLIST_HEAD(clk_root_list);
 static HLIST_HEAD(clk_orphan_list);
 static LIST_HEAD(clk_notifier_list);
 
+/* List of registered clks that use runtime PM */
+static HLIST_HEAD(clk_rpm_list);
+static DEFINE_MUTEX(clk_rpm_list_lock);
+
 static const struct hlist_head *all_lists[] = {
        &clk_root_list,
        &clk_orphan_list,
@@ -59,6 +63,7 @@ struct clk_core {
        struct clk_hw           *hw;
        struct module           *owner;
        struct device           *dev;
+       struct hlist_node       rpm_node;
        struct device_node      *of_node;
        struct clk_core         *parent;
        struct clk_parent_map   *parents;
@@ -122,6 +127,89 @@ static void clk_pm_runtime_put(struct clk_core *core)
        pm_runtime_put_sync(core->dev);
 }
 
+/**
+ * clk_pm_runtime_get_all() - Runtime "get" all clk provider devices
+ *
+ * Call clk_pm_runtime_get() on all runtime PM enabled clks in the clk tree so
+ * that disabling unused clks avoids a deadlock where a device is runtime PM
+ * resuming/suspending and the runtime PM callback is trying to grab the
+ * prepare_lock for something like clk_prepare_enable() while
+ * clk_disable_unused_subtree() holds the prepare_lock and is trying to runtime
+ * PM resume/suspend the device as well.
+ *
+ * Context: Acquires the 'clk_rpm_list_lock' and returns with the lock held on
+ * success. Otherwise the lock is released on failure.
+ *
+ * Return: 0 on success, negative errno otherwise.
+ */
+static int clk_pm_runtime_get_all(void)
+{
+       int ret;
+       struct clk_core *core, *failed;
+
+       /*
+        * Grab the list lock to prevent any new clks from being registered
+        * or unregistered until clk_pm_runtime_put_all().
+        */
+       mutex_lock(&clk_rpm_list_lock);
+
+       /*
+        * Runtime PM "get" all the devices that are needed for the clks
+        * currently registered. Do this without holding the prepare_lock, to
+        * avoid the deadlock.
+        */
+       hlist_for_each_entry(core, &clk_rpm_list, rpm_node) {
+               ret = clk_pm_runtime_get(core);
+               if (ret) {
+                       failed = core;
+                       pr_err("clk: Failed to runtime PM get '%s' for clk '%s'\n",
+                              dev_name(failed->dev), failed->name);
+                       goto err;
+               }
+       }
+
+       return 0;
+
+err:
+       hlist_for_each_entry(core, &clk_rpm_list, rpm_node) {
+               if (core == failed)
+                       break;
+
+               clk_pm_runtime_put(core);
+       }
+       mutex_unlock(&clk_rpm_list_lock);
+
+       return ret;
+}
+
+/**
+ * clk_pm_runtime_put_all() - Runtime "put" all clk provider devices
+ *
+ * Put the runtime PM references taken in clk_pm_runtime_get_all() and release
+ * the 'clk_rpm_list_lock'.
+ */
+static void clk_pm_runtime_put_all(void)
+{
+       struct clk_core *core;
+
+       hlist_for_each_entry(core, &clk_rpm_list, rpm_node)
+               clk_pm_runtime_put(core);
+       mutex_unlock(&clk_rpm_list_lock);
+}
+
+static void clk_pm_runtime_init(struct clk_core *core)
+{
+       struct device *dev = core->dev;
+
+       if (dev && pm_runtime_enabled(dev)) {
+               core->rpm_enabled = true;
+
+               mutex_lock(&clk_rpm_list_lock);
+               hlist_add_head(&core->rpm_node, &clk_rpm_list);
+               mutex_unlock(&clk_rpm_list_lock);
+       }
+}
+
 /***           locking             ***/
 static void clk_prepare_lock(void)
 {
@@ -1381,9 +1469,6 @@ static void __init clk_unprepare_unused_subtree(struct clk_core *core)
        if (core->flags & CLK_IGNORE_UNUSED)
                return;
 
-       if (clk_pm_runtime_get(core))
-               return;
-
        if (clk_core_is_prepared(core)) {
                trace_clk_unprepare(core);
                if (core->ops->unprepare_unused)
@@ -1392,8 +1477,6 @@ static void __init clk_unprepare_unused_subtree(struct clk_core *core)
                        core->ops->unprepare(core->hw);
                trace_clk_unprepare_complete(core);
        }
-
-       clk_pm_runtime_put(core);
 }
 
 static void __init clk_disable_unused_subtree(struct clk_core *core)
@@ -1409,9 +1492,6 @@ static void __init clk_disable_unused_subtree(struct clk_core *core)
        if (core->flags & CLK_OPS_PARENT_ENABLE)
                clk_core_prepare_enable(core->parent);
 
-       if (clk_pm_runtime_get(core))
-               goto unprepare_out;
-
        flags = clk_enable_lock();
 
        if (core->enable_count)
@@ -1436,8 +1516,6 @@ static void __init clk_disable_unused_subtree(struct clk_core *core)
 
 unlock_out:
        clk_enable_unlock(flags);
-       clk_pm_runtime_put(core);
-unprepare_out:
        if (core->flags & CLK_OPS_PARENT_ENABLE)
                clk_core_disable_unprepare(core->parent);
 }
@@ -1453,6 +1531,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup);
 static int __init clk_disable_unused(void)
 {
        struct clk_core *core;
+       int ret;
 
        if (clk_ignore_unused) {
                pr_warn("clk: Not disabling unused clocks\n");
@@ -1461,6 +1540,13 @@ static int __init clk_disable_unused(void)
 
        pr_info("clk: Disabling unused clocks\n");
 
+       ret = clk_pm_runtime_get_all();
+       if (ret)
+               return ret;
+       /*
+        * Grab the prepare lock to keep the clk topology stable while iterating
+        * over clks.
+        */
        clk_prepare_lock();
 
        hlist_for_each_entry(core, &clk_root_list, child_node)
@@ -1477,6 +1563,8 @@ static int __init clk_disable_unused(void)
 
        clk_prepare_unlock();
 
+       clk_pm_runtime_put_all();
+
        return 0;
 }
 late_initcall_sync(clk_disable_unused);
@@ -3252,9 +3340,7 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
 {
        struct clk_core *child;
 
-       clk_pm_runtime_get(c);
        clk_summary_show_one(s, c, level);
-       clk_pm_runtime_put(c);
 
        hlist_for_each_entry(child, &c->children, child_node)
                clk_summary_show_subtree(s, child, level + 1);
@@ -3264,11 +3350,15 @@ static int clk_summary_show(struct seq_file *s, void *data)
 {
        struct clk_core *c;
        struct hlist_head **lists = s->private;
+       int ret;
 
        seq_puts(s, "                                 enable  prepare  protect                                duty  hardware                            connection\n");
        seq_puts(s, "   clock                          count    count    count        rate   accuracy phase  cycle    enable   consumer                         id\n");
        seq_puts(s, "---------------------------------------------------------------------------------------------------------------------------------------------\n");
 
+       ret = clk_pm_runtime_get_all();
+       if (ret)
+               return ret;
 
        clk_prepare_lock();
 
@@ -3277,6 +3367,7 @@ static int clk_summary_show(struct seq_file *s, void *data)
                        clk_summary_show_subtree(s, c, 0);
 
        clk_prepare_unlock();
+       clk_pm_runtime_put_all();
 
        return 0;
 }
@@ -3324,8 +3415,14 @@ static int clk_dump_show(struct seq_file *s, void *data)
        struct clk_core *c;
        bool first_node = true;
        struct hlist_head **lists = s->private;
+       int ret;
+
+       ret = clk_pm_runtime_get_all();
+       if (ret)
+               return ret;
 
        seq_putc(s, '{');
+
        clk_prepare_lock();
 
        for (; *lists; lists++) {
@@ -3338,6 +3435,7 @@ static int clk_dump_show(struct seq_file *s, void *data)
        }
 
        clk_prepare_unlock();
+       clk_pm_runtime_put_all();
 
        seq_puts(s, "}\n");
        return 0;
@@ -3981,8 +4079,6 @@ static int __clk_core_init(struct clk_core *core)
        }
 
        clk_core_reparent_orphans_nolock();
-
-       kref_init(&core->ref);
 out:
        clk_pm_runtime_put(core);
 unlock:
@@ -4211,6 +4307,22 @@ static void clk_core_free_parent_map(struct clk_core *core)
        kfree(core->parents);
 }
 
+/* Free memory allocated for a struct clk_core */
+static void __clk_release(struct kref *ref)
+{
+       struct clk_core *core = container_of(ref, struct clk_core, ref);
+
+       if (core->rpm_enabled) {
+               mutex_lock(&clk_rpm_list_lock);
+               hlist_del(&core->rpm_node);
+               mutex_unlock(&clk_rpm_list_lock);
+       }
+
+       clk_core_free_parent_map(core);
+       kfree_const(core->name);
+       kfree(core);
+}
+
 static struct clk *
 __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
 {
@@ -4231,6 +4343,8 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
                goto fail_out;
        }
 
+       kref_init(&core->ref);
+
        core->name = kstrdup_const(init->name, GFP_KERNEL);
        if (!core->name) {
                ret = -ENOMEM;
@@ -4243,9 +4357,8 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
        }
        core->ops = init->ops;
 
-       if (dev && pm_runtime_enabled(dev))
-               core->rpm_enabled = true;
        core->dev = dev;
+       clk_pm_runtime_init(core);
        core->of_node = np;
        if (dev && dev->driver)
                core->owner = dev->driver->owner;
@@ -4285,12 +4398,10 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
        hw->clk = NULL;
 
 fail_create_clk:
-       clk_core_free_parent_map(core);
 fail_parents:
 fail_ops:
-       kfree_const(core->name);
 fail_name:
-       kfree(core);
+       kref_put(&core->ref, __clk_release);
 fail_out:
        return ERR_PTR(ret);
 }
@@ -4370,18 +4481,6 @@ int of_clk_hw_register(struct device_node *node, struct clk_hw *hw)
 }
 EXPORT_SYMBOL_GPL(of_clk_hw_register);
 
-/* Free memory allocated for a clock. */
-static void __clk_release(struct kref *ref)
-{
-       struct clk_core *core = container_of(ref, struct clk_core, ref);
-
-       lockdep_assert_held(&prepare_lock);
-
-       clk_core_free_parent_map(core);
-       kfree_const(core->name);
-       kfree(core);
-}
-
 /*
  * Empty clk_ops for unregistered clocks. These are used temporarily
  * after clk_unregister() was called on a clock and until last clock
@@ -4472,7 +4571,8 @@ void clk_unregister(struct clk *clk)
        if (ops == &clk_nodrv_ops) {
                pr_err("%s: unregistered clock: %s\n", __func__,
                       clk->core->name);
-               goto unlock;
+               clk_prepare_unlock();
+               return;
        }
        /*
         * Assign empty clock ops for consumers that might still hold
@@ -4506,11 +4606,10 @@ void clk_unregister(struct clk *clk)
        if (clk->core->protect_count)
                pr_warn("%s: unregistering protected clock: %s\n",
                                        __func__, clk->core->name);
+       clk_prepare_unlock();
 
        kref_put(&clk->core->ref, __clk_release);
        free_clk(clk);
-unlock:
-       clk_prepare_unlock();
 }
 EXPORT_SYMBOL_GPL(clk_unregister);
 
@@ -4669,13 +4768,11 @@ void __clk_put(struct clk *clk)
        if (clk->min_rate > 0 || clk->max_rate < ULONG_MAX)
                clk_set_rate_range_nolock(clk, 0, ULONG_MAX);
 
-       owner = clk->core->owner;
-       kref_put(&clk->core->ref, __clk_release);
-
        clk_prepare_unlock();
 
+       owner = clk->core->owner;
+       kref_put(&clk->core->ref, __clk_release);
        module_put(owner);
-
        free_clk(clk);
 }
 
index 449041f8abbc9a1cd97fa7d3807634653e677849..c8c023afe3e5adaf416ac413c7767812f7b97ab3 100644 (file)
@@ -156,7 +156,7 @@ static const struct mtk_gate infra_clks[] = {
        GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P1, "infra_pcie_peri_ck_26m_ck_p1",
                    "csw_infra_f26m_sel", 8),
        GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P2, "infra_pcie_peri_ck_26m_ck_p2",
-                   "csw_infra_f26m_sel", 9),
+                   "infra_pcie_peri_ck_26m_ck_p3", 9),
        GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P3, "infra_pcie_peri_ck_26m_ck_p3",
                    "csw_infra_f26m_sel", 10),
        /* INFRA1 */
index 2e55368dc4d82095b5baceb7b744a9ed4b1350b4..bd37ab4d1a9bb3252ae54a2f3a3d3d241b1daa3a 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
 #include "clk-mtk.h"
@@ -494,6 +495,16 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
                        return IS_ERR(base) ? PTR_ERR(base) : -ENOMEM;
        }
 
+
+       devm_pm_runtime_enable(&pdev->dev);
+       /*
+        * Do a pm_runtime_resume_and_get() to workaround a possible
+        * deadlock between clk_register() and the genpd framework.
+        */
+       r = pm_runtime_resume_and_get(&pdev->dev);
+       if (r)
+               return r;
+
        /* Calculate how many clk_hw_onecell_data entries to allocate */
        num_clks = mcd->num_clks + mcd->num_composite_clks;
        num_clks += mcd->num_fixed_clks + mcd->num_factor_clks;
@@ -574,6 +585,8 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
                        goto unregister_clks;
        }
 
+       pm_runtime_put(&pdev->dev);
+
        return r;
 
 unregister_clks:
@@ -604,6 +617,8 @@ free_data:
 free_base:
        if (mcd->shared_io && base)
                iounmap(base);
+
+       pm_runtime_put(&pdev->dev);
        return r;
 }
 
index 8602c02047d0481b28e7c7da75ddb1564aa3da14..45c5255bcd11bae69b83138ba1d5e52a8a3f3be8 100644 (file)
@@ -768,6 +768,7 @@ static struct clk_smd_rpm *msm8976_clks[] = {
 
 static const struct rpm_smd_clk_desc rpm_clk_msm8976 = {
        .clks = msm8976_clks,
+       .num_clks = ARRAY_SIZE(msm8976_clks),
        .icc_clks = bimc_pcnoc_snoc_smmnoc_icc_clks,
        .num_icc_clks = ARRAY_SIZE(bimc_pcnoc_snoc_smmnoc_icc_clks),
 };
index e7a4068b9f3906f99d9d5ca444fe903b237811b6..df9618ab7eea1fb0422ee73fd21938e6fc77e257 100644 (file)
@@ -487,9 +487,14 @@ int gdsc_register(struct gdsc_desc *desc,
                if (!scs[i] || !scs[i]->supply)
                        continue;
 
-               scs[i]->rsupply = devm_regulator_get(dev, scs[i]->supply);
-               if (IS_ERR(scs[i]->rsupply))
-                       return PTR_ERR(scs[i]->rsupply);
+               scs[i]->rsupply = devm_regulator_get_optional(dev, scs[i]->supply);
+               if (IS_ERR(scs[i]->rsupply)) {
+                       ret = PTR_ERR(scs[i]->rsupply);
+                       if (ret != -ENODEV)
+                               return ret;
+
+                       scs[i]->rsupply = NULL;
+               }
        }
 
        data->num_domains = num;
index 3484e6cc80ad10d1eceaba017de2a9bfc7602880..503c6f5b20d5c5538dc2bfc44afbc594df0878d6 100644 (file)
@@ -13,9 +13,9 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
-#include <linux/property.h>
 
 #define EXYNOS_CLKOUT_NR_CLKS          1
 #define EXYNOS_CLKOUT_PARENTS          32
@@ -84,17 +84,24 @@ MODULE_DEVICE_TABLE(of, exynos_clkout_ids);
 static int exynos_clkout_match_parent_dev(struct device *dev, u32 *mux_mask)
 {
        const struct exynos_clkout_variant *variant;
+       const struct of_device_id *match;
 
        if (!dev->parent) {
                dev_err(dev, "not instantiated from MFD\n");
                return -EINVAL;
        }
 
-       variant = device_get_match_data(dev->parent);
-       if (!variant) {
+       /*
+        * 'exynos_clkout_ids' arrays is not the ids array matched by
+        * the dev->parent driver, so of_device_get_match_data() or
+        * device_get_match_data() cannot be used here.
+        */
+       match = of_match_device(exynos_clkout_ids, dev->parent);
+       if (!match) {
                dev_err(dev, "cannot match parent device\n");
                return -EINVAL;
        }
+       variant = match->data;
 
        *mux_mask = variant->mux_mask;
 
index 8951ffc14ff52c5a2bd7d6be60f47539cad36fb1..6a4b2b9ef30a82e1721e21695f299351a378f8fb 100644 (file)
@@ -182,6 +182,8 @@ static struct ccu_nkm pll_mipi_clk = {
                                              &ccu_nkm_ops,
                                              CLK_SET_RATE_UNGATE | CLK_SET_RATE_PARENT),
                .features       = CCU_FEATURE_CLOSEST_RATE,
+               .min_rate       = 500000000,
+               .max_rate       = 1400000000,
        },
 };
 
index 42568c6161814dc797079d1ee224bc7a2e6847a8..892df807275c8e57b1b53112faece02a47f22f6e 100644 (file)
@@ -1181,11 +1181,18 @@ static const u32 usb2_clk_regs[] = {
        SUN50I_H6_USB3_CLK_REG,
 };
 
+static struct ccu_mux_nb sun50i_h6_cpu_nb = {
+       .common         = &cpux_clk.common,
+       .cm             = &cpux_clk.mux,
+       .delay_us       = 1,
+       .bypass_index   = 0, /* index of 24 MHz oscillator */
+};
+
 static int sun50i_h6_ccu_probe(struct platform_device *pdev)
 {
        void __iomem *reg;
+       int i, ret;
        u32 val;
-       int i;
 
        reg = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(reg))
@@ -1252,7 +1259,15 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
        val |= BIT(24);
        writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG);
 
-       return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc);
+       ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc);
+       if (ret)
+               return ret;
+
+       /* Reparent CPU during PLL CPUX rate changes */
+       ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
+                                 &sun50i_h6_cpu_nb);
+
+       return 0;
 }
 
 static const struct of_device_id sun50i_h6_ccu_ids[] = {
index 8babce55302f5f9dd9ddd59ef0113e3af5171d37..ac0091b4ce2425b77750619383531191c228e7ed 100644 (file)
@@ -44,6 +44,16 @@ bool ccu_is_better_rate(struct ccu_common *common,
                        unsigned long current_rate,
                        unsigned long best_rate)
 {
+       unsigned long min_rate, max_rate;
+
+       clk_hw_get_rate_range(&common->hw, &min_rate, &max_rate);
+
+       if (current_rate > max_rate)
+               return false;
+
+       if (current_rate < min_rate)
+               return false;
+
        if (common->features & CCU_FEATURE_CLOSEST_RATE)
                return abs(current_rate - target_rate) < abs(best_rate - target_rate);
 
@@ -122,6 +132,7 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
 
        for (i = 0; i < desc->hw_clks->num ; i++) {
                struct clk_hw *hw = desc->hw_clks->hws[i];
+               struct ccu_common *common = hw_to_ccu_common(hw);
                const char *name;
 
                if (!hw)
@@ -136,6 +147,14 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
                        pr_err("Couldn't register clock %d - %s\n", i, name);
                        goto err_clk_unreg;
                }
+
+               if (common->max_rate)
+                       clk_hw_set_rate_range(hw, common->min_rate,
+                                             common->max_rate);
+               else
+                       WARN(common->min_rate,
+                            "No max_rate, ignoring min_rate of clock %d - %s\n",
+                            i, name);
        }
 
        ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
index 942a72c094374435d73e9f27ddfd04af4f241fd4..329734f8cf42b41263fbc4eb2de9bb1315e498e1 100644 (file)
@@ -31,6 +31,9 @@ struct ccu_common {
        u16             lock_reg;
        u32             prediv;
 
+       unsigned long   min_rate;
+       unsigned long   max_rate;
+
        unsigned long   features;
        spinlock_t      *lock;
        struct clk_hw   hw;
index 4536ed43f65b2763ec4612a000eb4dae70875c17..84dce5184a77ae7903035c8905dbff30cea390ca 100644 (file)
@@ -641,33 +641,22 @@ static int vmk80xx_find_usb_endpoints(struct comedi_device *dev)
        struct vmk80xx_private *devpriv = dev->private;
        struct usb_interface *intf = comedi_to_usb_interface(dev);
        struct usb_host_interface *iface_desc = intf->cur_altsetting;
-       struct usb_endpoint_descriptor *ep_desc;
-       int i;
-
-       if (iface_desc->desc.bNumEndpoints != 2)
-               return -ENODEV;
-
-       for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
-               ep_desc = &iface_desc->endpoint[i].desc;
-
-               if (usb_endpoint_is_int_in(ep_desc) ||
-                   usb_endpoint_is_bulk_in(ep_desc)) {
-                       if (!devpriv->ep_rx)
-                               devpriv->ep_rx = ep_desc;
-                       continue;
-               }
+       struct usb_endpoint_descriptor *ep_rx_desc, *ep_tx_desc;
+       int ret;
 
-               if (usb_endpoint_is_int_out(ep_desc) ||
-                   usb_endpoint_is_bulk_out(ep_desc)) {
-                       if (!devpriv->ep_tx)
-                               devpriv->ep_tx = ep_desc;
-                       continue;
-               }
-       }
+       if (devpriv->model == VMK8061_MODEL)
+               ret = usb_find_common_endpoints(iface_desc, &ep_rx_desc,
+                                               &ep_tx_desc, NULL, NULL);
+       else
+               ret = usb_find_common_endpoints(iface_desc, NULL, NULL,
+                                               &ep_rx_desc, &ep_tx_desc);
 
-       if (!devpriv->ep_rx || !devpriv->ep_tx)
+       if (ret)
                return -ENODEV;
 
+       devpriv->ep_rx = ep_rx_desc;
+       devpriv->ep_tx = ep_tx_desc;
+
        if (!usb_endpoint_maxp(devpriv->ep_rx) || !usb_endpoint_maxp(devpriv->ep_tx))
                return -EINVAL;
 
index 2015c9fcc3c9145e997d15d834aeace8728fc346..6a342b0c014034b06c320f0d0c8b69d3dbc4596c 100644 (file)
@@ -50,7 +50,8 @@
 
 #define AMD_PSTATE_TRANSITION_LATENCY  20000
 #define AMD_PSTATE_TRANSITION_DELAY    1000
-#define AMD_PSTATE_PREFCORE_THRESHOLD  166
+#define CPPC_HIGHEST_PERF_PERFORMANCE  196
+#define CPPC_HIGHEST_PERF_DEFAULT      166
 
 /*
  * TODO: We need more time to fine tune processors with shared memory solution
@@ -67,6 +68,7 @@ static struct cpufreq_driver amd_pstate_epp_driver;
 static int cppc_state = AMD_PSTATE_UNDEFINED;
 static bool cppc_enabled;
 static bool amd_pstate_prefcore = true;
+static struct quirk_entry *quirks;
 
 /*
  * AMD Energy Preference Performance (EPP)
@@ -111,6 +113,41 @@ static unsigned int epp_values[] = {
 
 typedef int (*cppc_mode_transition_fn)(int);
 
+static struct quirk_entry quirk_amd_7k62 = {
+       .nominal_freq = 2600,
+       .lowest_freq = 550,
+};
+
+static int __init dmi_matched_7k62_bios_bug(const struct dmi_system_id *dmi)
+{
+       /**
+        * match the broken bios for family 17h processor support CPPC V2
+        * broken BIOS lack of nominal_freq and lowest_freq capabilities
+        * definition in ACPI tables
+        */
+       if (boot_cpu_has(X86_FEATURE_ZEN2)) {
+               quirks = dmi->driver_data;
+               pr_info("Overriding nominal and lowest frequencies for %s\n", dmi->ident);
+               return 1;
+       }
+
+       return 0;
+}
+
+static const struct dmi_system_id amd_pstate_quirks_table[] __initconst = {
+       {
+               .callback = dmi_matched_7k62_bios_bug,
+               .ident = "AMD EPYC 7K62",
+               .matches = {
+                       DMI_MATCH(DMI_BIOS_VERSION, "5.14"),
+                       DMI_MATCH(DMI_BIOS_RELEASE, "12/12/2019"),
+               },
+               .driver_data = &quirk_amd_7k62,
+       },
+       {}
+};
+MODULE_DEVICE_TABLE(dmi, amd_pstate_quirks_table);
+
 static inline int get_mode_idx_from_str(const char *str, size_t size)
 {
        int i;
@@ -290,6 +327,21 @@ static inline int amd_pstate_enable(bool enable)
        return static_call(amd_pstate_enable)(enable);
 }
 
+static u32 amd_pstate_highest_perf_set(struct amd_cpudata *cpudata)
+{
+       struct cpuinfo_x86 *c = &cpu_data(0);
+
+       /*
+        * For AMD CPUs with Family ID 19H and Model ID range 0x70 to 0x7f,
+        * the highest performance level is set to 196.
+        * https://bugzilla.kernel.org/show_bug.cgi?id=218759
+        */
+       if (c->x86 == 0x19 && (c->x86_model >= 0x70 && c->x86_model <= 0x7f))
+               return CPPC_HIGHEST_PERF_PERFORMANCE;
+
+       return CPPC_HIGHEST_PERF_DEFAULT;
+}
+
 static int pstate_init_perf(struct amd_cpudata *cpudata)
 {
        u64 cap1;
@@ -306,7 +358,7 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)
         * the default max perf.
         */
        if (cpudata->hw_prefcore)
-               highest_perf = AMD_PSTATE_PREFCORE_THRESHOLD;
+               highest_perf = amd_pstate_highest_perf_set(cpudata);
        else
                highest_perf = AMD_CPPC_HIGHEST_PERF(cap1);
 
@@ -330,7 +382,7 @@ static int cppc_init_perf(struct amd_cpudata *cpudata)
                return ret;
 
        if (cpudata->hw_prefcore)
-               highest_perf = AMD_PSTATE_PREFCORE_THRESHOLD;
+               highest_perf = amd_pstate_highest_perf_set(cpudata);
        else
                highest_perf = cppc_perf.highest_perf;
 
@@ -604,78 +656,6 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
        cpufreq_cpu_put(policy);
 }
 
-static int amd_get_min_freq(struct amd_cpudata *cpudata)
-{
-       struct cppc_perf_caps cppc_perf;
-
-       int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
-       if (ret)
-               return ret;
-
-       /* Switch to khz */
-       return cppc_perf.lowest_freq * 1000;
-}
-
-static int amd_get_max_freq(struct amd_cpudata *cpudata)
-{
-       struct cppc_perf_caps cppc_perf;
-       u32 max_perf, max_freq, nominal_freq, nominal_perf;
-       u64 boost_ratio;
-
-       int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
-       if (ret)
-               return ret;
-
-       nominal_freq = cppc_perf.nominal_freq;
-       nominal_perf = READ_ONCE(cpudata->nominal_perf);
-       max_perf = READ_ONCE(cpudata->highest_perf);
-
-       boost_ratio = div_u64(max_perf << SCHED_CAPACITY_SHIFT,
-                             nominal_perf);
-
-       max_freq = nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT;
-
-       /* Switch to khz */
-       return max_freq * 1000;
-}
-
-static int amd_get_nominal_freq(struct amd_cpudata *cpudata)
-{
-       struct cppc_perf_caps cppc_perf;
-
-       int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
-       if (ret)
-               return ret;
-
-       /* Switch to khz */
-       return cppc_perf.nominal_freq * 1000;
-}
-
-static int amd_get_lowest_nonlinear_freq(struct amd_cpudata *cpudata)
-{
-       struct cppc_perf_caps cppc_perf;
-       u32 lowest_nonlinear_freq, lowest_nonlinear_perf,
-           nominal_freq, nominal_perf;
-       u64 lowest_nonlinear_ratio;
-
-       int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
-       if (ret)
-               return ret;
-
-       nominal_freq = cppc_perf.nominal_freq;
-       nominal_perf = READ_ONCE(cpudata->nominal_perf);
-
-       lowest_nonlinear_perf = cppc_perf.lowest_nonlinear_perf;
-
-       lowest_nonlinear_ratio = div_u64(lowest_nonlinear_perf << SCHED_CAPACITY_SHIFT,
-                                        nominal_perf);
-
-       lowest_nonlinear_freq = nominal_freq * lowest_nonlinear_ratio >> SCHED_CAPACITY_SHIFT;
-
-       /* Switch to khz */
-       return lowest_nonlinear_freq * 1000;
-}
-
 static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state)
 {
        struct amd_cpudata *cpudata = policy->driver_data;
@@ -828,9 +808,93 @@ free_cpufreq_put:
        mutex_unlock(&amd_pstate_driver_lock);
 }
 
+/*
+ * Get pstate transition delay time from ACPI tables that firmware set
+ * instead of using hardcode value directly.
+ */
+static u32 amd_pstate_get_transition_delay_us(unsigned int cpu)
+{
+       u32 transition_delay_ns;
+
+       transition_delay_ns = cppc_get_transition_latency(cpu);
+       if (transition_delay_ns == CPUFREQ_ETERNAL)
+               return AMD_PSTATE_TRANSITION_DELAY;
+
+       return transition_delay_ns / NSEC_PER_USEC;
+}
+
+/*
+ * Get pstate transition latency value from ACPI tables that firmware
+ * set instead of using hardcode value directly.
+ */
+static u32 amd_pstate_get_transition_latency(unsigned int cpu)
+{
+       u32 transition_latency;
+
+       transition_latency = cppc_get_transition_latency(cpu);
+       if (transition_latency  == CPUFREQ_ETERNAL)
+               return AMD_PSTATE_TRANSITION_LATENCY;
+
+       return transition_latency;
+}
+
+/*
+ * amd_pstate_init_freq: Initialize the max_freq, min_freq,
+ *                       nominal_freq and lowest_nonlinear_freq for
+ *                       the @cpudata object.
+ *
+ *  Requires: highest_perf, lowest_perf, nominal_perf and
+ *            lowest_nonlinear_perf members of @cpudata to be
+ *            initialized.
+ *
+ *  Returns 0 on success, non-zero value on failure.
+ */
+static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
+{
+       int ret;
+       u32 min_freq;
+       u32 highest_perf, max_freq;
+       u32 nominal_perf, nominal_freq;
+       u32 lowest_nonlinear_perf, lowest_nonlinear_freq;
+       u32 boost_ratio, lowest_nonlinear_ratio;
+       struct cppc_perf_caps cppc_perf;
+
+       ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
+       if (ret)
+               return ret;
+
+       if (quirks && quirks->lowest_freq)
+               min_freq = quirks->lowest_freq * 1000;
+       else
+               min_freq = cppc_perf.lowest_freq * 1000;
+
+       if (quirks && quirks->nominal_freq)
+               nominal_freq = quirks->nominal_freq ;
+       else
+               nominal_freq = cppc_perf.nominal_freq;
+
+       nominal_perf = READ_ONCE(cpudata->nominal_perf);
+
+       highest_perf = READ_ONCE(cpudata->highest_perf);
+       boost_ratio = div_u64(highest_perf << SCHED_CAPACITY_SHIFT, nominal_perf);
+       max_freq = (nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT) * 1000;
+
+       lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
+       lowest_nonlinear_ratio = div_u64(lowest_nonlinear_perf << SCHED_CAPACITY_SHIFT,
+                                        nominal_perf);
+       lowest_nonlinear_freq = (nominal_freq * lowest_nonlinear_ratio >> SCHED_CAPACITY_SHIFT) * 1000;
+
+       WRITE_ONCE(cpudata->min_freq, min_freq);
+       WRITE_ONCE(cpudata->lowest_nonlinear_freq, lowest_nonlinear_freq);
+       WRITE_ONCE(cpudata->nominal_freq, nominal_freq);
+       WRITE_ONCE(cpudata->max_freq, max_freq);
+
+       return 0;
+}
+
 static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
 {
-       int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret;
+       int min_freq, max_freq, nominal_freq, ret;
        struct device *dev;
        struct amd_cpudata *cpudata;
 
@@ -855,20 +919,25 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
        if (ret)
                goto free_cpudata1;
 
-       min_freq = amd_get_min_freq(cpudata);
-       max_freq = amd_get_max_freq(cpudata);
-       nominal_freq = amd_get_nominal_freq(cpudata);
-       lowest_nonlinear_freq = amd_get_lowest_nonlinear_freq(cpudata);
+       ret = amd_pstate_init_freq(cpudata);
+       if (ret)
+               goto free_cpudata1;
+
+       min_freq = READ_ONCE(cpudata->min_freq);
+       max_freq = READ_ONCE(cpudata->max_freq);
+       nominal_freq = READ_ONCE(cpudata->nominal_freq);
 
-       if (min_freq < 0 || max_freq < 0 || min_freq > max_freq) {
-               dev_err(dev, "min_freq(%d) or max_freq(%d) value is incorrect\n",
-                       min_freq, max_freq);
+       if (min_freq <= 0 || max_freq <= 0 ||
+           nominal_freq <= 0 || min_freq > max_freq) {
+               dev_err(dev,
+                       "min_freq(%d) or max_freq(%d) or nominal_freq (%d) value is incorrect, check _CPC in ACPI tables\n",
+                       min_freq, max_freq, nominal_freq);
                ret = -EINVAL;
                goto free_cpudata1;
        }
 
-       policy->cpuinfo.transition_latency = AMD_PSTATE_TRANSITION_LATENCY;
-       policy->transition_delay_us = AMD_PSTATE_TRANSITION_DELAY;
+       policy->cpuinfo.transition_latency = amd_pstate_get_transition_latency(policy->cpu);
+       policy->transition_delay_us = amd_pstate_get_transition_delay_us(policy->cpu);
 
        policy->min = min_freq;
        policy->max = max_freq;
@@ -896,13 +965,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
                goto free_cpudata2;
        }
 
-       /* Initial processor data capability frequencies */
-       cpudata->max_freq = max_freq;
-       cpudata->min_freq = min_freq;
        cpudata->max_limit_freq = max_freq;
        cpudata->min_limit_freq = min_freq;
-       cpudata->nominal_freq = nominal_freq;
-       cpudata->lowest_nonlinear_freq = lowest_nonlinear_freq;
 
        policy->driver_data = cpudata;
 
@@ -966,7 +1030,7 @@ static ssize_t show_amd_pstate_max_freq(struct cpufreq_policy *policy,
        int max_freq;
        struct amd_cpudata *cpudata = policy->driver_data;
 
-       max_freq = amd_get_max_freq(cpudata);
+       max_freq = READ_ONCE(cpudata->max_freq);
        if (max_freq < 0)
                return max_freq;
 
@@ -979,7 +1043,7 @@ static ssize_t show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *poli
        int freq;
        struct amd_cpudata *cpudata = policy->driver_data;
 
-       freq = amd_get_lowest_nonlinear_freq(cpudata);
+       freq = READ_ONCE(cpudata->lowest_nonlinear_freq);
        if (freq < 0)
                return freq;
 
@@ -1290,7 +1354,7 @@ static bool amd_pstate_acpi_pm_profile_undefined(void)
 
 static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
 {
-       int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret;
+       int min_freq, max_freq, nominal_freq, ret;
        struct amd_cpudata *cpudata;
        struct device *dev;
        u64 value;
@@ -1317,13 +1381,18 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
        if (ret)
                goto free_cpudata1;
 
-       min_freq = amd_get_min_freq(cpudata);
-       max_freq = amd_get_max_freq(cpudata);
-       nominal_freq = amd_get_nominal_freq(cpudata);
-       lowest_nonlinear_freq = amd_get_lowest_nonlinear_freq(cpudata);
-       if (min_freq < 0 || max_freq < 0 || min_freq > max_freq) {
-               dev_err(dev, "min_freq(%d) or max_freq(%d) value is incorrect\n",
-                               min_freq, max_freq);
+       ret = amd_pstate_init_freq(cpudata);
+       if (ret)
+               goto free_cpudata1;
+
+       min_freq = READ_ONCE(cpudata->min_freq);
+       max_freq = READ_ONCE(cpudata->max_freq);
+       nominal_freq = READ_ONCE(cpudata->nominal_freq);
+       if (min_freq <= 0 || max_freq <= 0 ||
+           nominal_freq <= 0 || min_freq > max_freq) {
+               dev_err(dev,
+                       "min_freq(%d) or max_freq(%d) or nominal_freq(%d) value is incorrect, check _CPC in ACPI tables\n",
+                       min_freq, max_freq, nominal_freq);
                ret = -EINVAL;
                goto free_cpudata1;
        }
@@ -1333,12 +1402,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
        /* It will be updated by governor */
        policy->cur = policy->cpuinfo.min_freq;
 
-       /* Initial processor data capability frequencies */
-       cpudata->max_freq = max_freq;
-       cpudata->min_freq = min_freq;
-       cpudata->nominal_freq = nominal_freq;
-       cpudata->lowest_nonlinear_freq = lowest_nonlinear_freq;
-
        policy->driver_data = cpudata;
 
        cpudata->epp_cached = amd_pstate_get_epp(cpudata, 0);
@@ -1656,6 +1719,11 @@ static int __init amd_pstate_init(void)
        if (cpufreq_get_current_driver())
                return -EEXIST;
 
+       quirks = NULL;
+
+       /* check if this machine need CPPC quirks */
+       dmi_check_system(amd_pstate_quirks_table);
+
        switch (cppc_state) {
        case AMD_PSTATE_UNDEFINED:
                /* Disable on the following configs by default:
index 1a1857b0a6f482d4e07a9c4a58ff66bb5d98cebd..ea8438550b490160d219c791d35343776eabea0b 100644 (file)
@@ -481,9 +481,12 @@ static bool brcm_avs_is_firmware_loaded(struct private_data *priv)
 static unsigned int brcm_avs_cpufreq_get(unsigned int cpu)
 {
        struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+       struct private_data *priv;
+
        if (!policy)
                return 0;
-       struct private_data *priv = policy->driver_data;
+
+       priv = policy->driver_data;
 
        cpufreq_cpu_put(policy);
 
index 64420d9cfd1ed3cbec1c6a25a7640c4afa875466..15f1d41920a3397b2900a1d210a4ef644774a270 100644 (file)
@@ -741,10 +741,15 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpu)
 {
        struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0};
        struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-       struct cppc_cpudata *cpu_data = policy->driver_data;
+       struct cppc_cpudata *cpu_data;
        u64 delivered_perf;
        int ret;
 
+       if (!policy)
+               return -ENODEV;
+
+       cpu_data = policy->driver_data;
+
        cpufreq_cpu_put(policy);
 
        ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t0);
@@ -822,10 +827,15 @@ static struct cpufreq_driver cppc_cpufreq_driver = {
 static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu)
 {
        struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-       struct cppc_cpudata *cpu_data = policy->driver_data;
+       struct cppc_cpudata *cpu_data;
        u64 desired_perf;
        int ret;
 
+       if (!policy)
+               return -ENODEV;
+
+       cpu_data = policy->driver_data;
+
        cpufreq_cpu_put(policy);
 
        ret = cppc_get_desired_perf(cpu, &desired_perf);
index b993a498084bc87fc86f7e1cc0ab88d67c309568..c74dd1e01e0d6832092a725d025f0fa89603b360 100644 (file)
@@ -104,6 +104,9 @@ static const struct of_device_id allowlist[] __initconst = {
  */
 static const struct of_device_id blocklist[] __initconst = {
        { .compatible = "allwinner,sun50i-h6", },
+       { .compatible = "allwinner,sun50i-h616", },
+       { .compatible = "allwinner,sun50i-h618", },
+       { .compatible = "allwinner,sun50i-h700", },
 
        { .compatible = "apple,arm-platform", },
 
@@ -195,19 +198,18 @@ static const struct of_device_id blocklist[] __initconst = {
 
 static bool __init cpu0_node_has_opp_v2_prop(void)
 {
-       struct device_node *np = of_cpu_device_node_get(0);
+       struct device_node *np __free(device_node) = of_cpu_device_node_get(0);
        bool ret = false;
 
        if (of_property_present(np, "operating-points-v2"))
                ret = true;
 
-       of_node_put(np);
        return ret;
 }
 
 static int __init cpufreq_dt_platdev_init(void)
 {
-       struct device_node *np = of_find_node_by_path("/");
+       struct device_node *np __free(device_node) = of_find_node_by_path("/");
        const struct of_device_id *match;
        const void *data = NULL;
 
@@ -223,11 +225,9 @@ static int __init cpufreq_dt_platdev_init(void)
        if (cpu0_node_has_opp_v2_prop() && !of_match_node(blocklist, np))
                goto create_pdev;
 
-       of_node_put(np);
        return -ENODEV;
 
 create_pdev:
-       of_node_put(np);
        return PTR_ERR_OR_ZERO(platform_device_register_data(NULL, "cpufreq-dt",
                               -1, data,
                               sizeof(struct cpufreq_dt_platform_data)));
index 2d83bbc65dd0bd69c8b035790ddc1217ddde9fb4..907e22632fda866738695bbfa9cd28374f95d563 100644 (file)
@@ -68,12 +68,9 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index)
  */
 static const char *find_supply_name(struct device *dev)
 {
-       struct device_node *np;
+       struct device_node *np __free(device_node) = of_node_get(dev->of_node);
        struct property *pp;
        int cpu = dev->id;
-       const char *name = NULL;
-
-       np = of_node_get(dev->of_node);
 
        /* This must be valid for sure */
        if (WARN_ON(!np))
@@ -82,22 +79,16 @@ static const char *find_supply_name(struct device *dev)
        /* Try "cpu0" for older DTs */
        if (!cpu) {
                pp = of_find_property(np, "cpu0-supply", NULL);
-               if (pp) {
-                       name = "cpu0";
-                       goto node_put;
-               }
+               if (pp)
+                       return "cpu0";
        }
 
        pp = of_find_property(np, "cpu-supply", NULL);
-       if (pp) {
-               name = "cpu";
-               goto node_put;
-       }
+       if (pp)
+               return "cpu";
 
        dev_dbg(dev, "no regulator for cpu%d\n", cpu);
-node_put:
-       of_node_put(np);
-       return name;
+       return NULL;
 }
 
 static int cpufreq_init(struct cpufreq_policy *policy)
index 66e10a19d76abc3476282c69060c0cac4a815084..fd9c3ed21f49c4d3b9e10e0679078cff385253d2 100644 (file)
@@ -1679,10 +1679,13 @@ static void __cpufreq_offline(unsigned int cpu, struct cpufreq_policy *policy)
         */
        if (cpufreq_driver->offline) {
                cpufreq_driver->offline(policy);
-       } else if (cpufreq_driver->exit) {
-               cpufreq_driver->exit(policy);
-               policy->freq_table = NULL;
+               return;
        }
+
+       if (cpufreq_driver->exit)
+               cpufreq_driver->exit(policy);
+
+       policy->freq_table = NULL;
 }
 
 static int cpufreq_offline(unsigned int cpu)
@@ -1740,7 +1743,7 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
        }
 
        /* We did light-weight exit earlier, do full tear down now */
-       if (cpufreq_driver->offline)
+       if (cpufreq_driver->offline && cpufreq_driver->exit)
                cpufreq_driver->exit(policy);
 
        up_write(&policy->rwsem);
index c17dc51a5a022d4b85558f69f3c21ec27ec2ba00..10e80d912b8d85259e77260fdf9a603ab95de70f 100644 (file)
@@ -70,7 +70,7 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy,
                                   struct cpufreq_frequency_table *table)
 {
        struct cpufreq_frequency_table *pos;
-       unsigned int freq, next_larger = ~0;
+       unsigned int freq, prev_smaller = 0;
        bool found = false;
 
        pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n",
@@ -86,12 +86,12 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy,
                        break;
                }
 
-               if ((next_larger > freq) && (freq > policy->max))
-                       next_larger = freq;
+               if ((prev_smaller < freq) && (freq <= policy->max))
+                       prev_smaller = freq;
        }
 
        if (!found) {
-               policy->max = next_larger;
+               policy->max = prev_smaller;
                cpufreq_verify_within_cpu_limits(policy);
        }
 
@@ -194,7 +194,7 @@ int cpufreq_table_index_unsorted(struct cpufreq_policy *policy,
        }
        if (optimal.driver_data > i) {
                if (suboptimal.driver_data > i) {
-                       WARN(1, "Invalid frequency table: %d\n", policy->cpu);
+                       WARN(1, "Invalid frequency table: %u\n", policy->cpu);
                        return 0;
                }
 
@@ -254,7 +254,7 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf,
                if (show_boost ^ (pos->flags & CPUFREQ_BOOST_FREQ))
                        continue;
 
-               count += sprintf(&buf[count], "%d ", pos->frequency);
+               count += sprintf(&buf[count], "%u ", pos->frequency);
        }
        count += sprintf(&buf[count], "\n");
 
index dbbf299f42197b55b9d9fbdf1d25f3c29b7d82fd..4b986c044741eda32d5e93f9457c7b606ccfacc0 100644 (file)
@@ -173,7 +173,6 @@ struct vid_data {
  *                     based on the MSR_IA32_MISC_ENABLE value and whether or
  *                     not the maximum reported turbo P-state is different from
  *                     the maximum reported non-turbo one.
- * @turbo_disabled_mf: The @turbo_disabled value reflected by cpuinfo.max_freq.
  * @min_perf_pct:      Minimum capacity limit in percent of the maximum turbo
  *                     P-state capacity.
  * @max_perf_pct:      Maximum capacity limit in percent of the maximum turbo
@@ -182,7 +181,6 @@ struct vid_data {
 struct global_params {
        bool no_turbo;
        bool turbo_disabled;
-       bool turbo_disabled_mf;
        int max_perf_pct;
        int min_perf_pct;
 };
@@ -213,7 +211,7 @@ struct global_params {
  * @epp_policy:                Last saved policy used to set EPP/EPB
  * @epp_default:       Power on default HWP energy performance
  *                     preference/bias
- * @epp_cached         Cached HWP energy-performance preference value
+ * @epp_cached:                Cached HWP energy-performance preference value
  * @hwp_req_cached:    Cached value of the last HWP Request MSR
  * @hwp_cap_cached:    Cached value of the last HWP Capabilities MSR
  * @last_io_update:    Last time when IO wake flag was set
@@ -292,11 +290,11 @@ struct pstate_funcs {
 
 static struct pstate_funcs pstate_funcs __read_mostly;
 
-static int hwp_active __read_mostly;
-static int hwp_mode_bdw __read_mostly;
-static bool per_cpu_limits __read_mostly;
+static bool hwp_active __ro_after_init;
+static int hwp_mode_bdw __ro_after_init;
+static bool per_cpu_limits __ro_after_init;
+static bool hwp_forced __ro_after_init;
 static bool hwp_boost __read_mostly;
-static bool hwp_forced __read_mostly;
 
 static struct cpufreq_driver *intel_pstate_driver __read_mostly;
 
@@ -594,12 +592,13 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu)
        cpu->pstate.min_pstate = intel_pstate_freq_to_hwp(cpu, freq);
 }
 
-static inline void update_turbo_state(void)
+static bool turbo_is_disabled(void)
 {
        u64 misc_en;
 
        rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
-       global.turbo_disabled = misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE;
+
+       return !!(misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE);
 }
 
 static int min_perf_pct_min(void)
@@ -1154,12 +1153,15 @@ static void intel_pstate_update_policies(void)
 static void __intel_pstate_update_max_freq(struct cpudata *cpudata,
                                           struct cpufreq_policy *policy)
 {
-       policy->cpuinfo.max_freq = global.turbo_disabled_mf ?
+       intel_pstate_get_hwp_cap(cpudata);
+
+       policy->cpuinfo.max_freq = READ_ONCE(global.no_turbo) ?
                        cpudata->pstate.max_freq : cpudata->pstate.turbo_freq;
+
        refresh_frequency_limits(policy);
 }
 
-static void intel_pstate_update_max_freq(unsigned int cpu)
+static void intel_pstate_update_limits(unsigned int cpu)
 {
        struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu);
 
@@ -1171,25 +1173,12 @@ static void intel_pstate_update_max_freq(unsigned int cpu)
        cpufreq_cpu_release(policy);
 }
 
-static void intel_pstate_update_limits(unsigned int cpu)
+static void intel_pstate_update_limits_for_all(void)
 {
-       mutex_lock(&intel_pstate_driver_lock);
-
-       update_turbo_state();
-       /*
-        * If turbo has been turned on or off globally, policy limits for
-        * all CPUs need to be updated to reflect that.
-        */
-       if (global.turbo_disabled_mf != global.turbo_disabled) {
-               global.turbo_disabled_mf = global.turbo_disabled;
-               arch_set_max_freq_ratio(global.turbo_disabled);
-               for_each_possible_cpu(cpu)
-                       intel_pstate_update_max_freq(cpu);
-       } else {
-               cpufreq_update_policy(cpu);
-       }
+       int cpu;
 
-       mutex_unlock(&intel_pstate_driver_lock);
+       for_each_possible_cpu(cpu)
+               intel_pstate_update_limits(cpu);
 }
 
 /************************** sysfs begin ************************/
@@ -1287,11 +1276,7 @@ static ssize_t show_no_turbo(struct kobject *kobj,
                return -EAGAIN;
        }
 
-       update_turbo_state();
-       if (global.turbo_disabled)
-               ret = sprintf(buf, "%u\n", global.turbo_disabled);
-       else
-               ret = sprintf(buf, "%u\n", global.no_turbo);
+       ret = sprintf(buf, "%u\n", global.no_turbo);
 
        mutex_unlock(&intel_pstate_driver_lock);
 
@@ -1302,32 +1287,34 @@ static ssize_t store_no_turbo(struct kobject *a, struct kobj_attribute *b,
                              const char *buf, size_t count)
 {
        unsigned int input;
-       int ret;
+       bool no_turbo;
 
-       ret = sscanf(buf, "%u", &input);
-       if (ret != 1)
+       if (sscanf(buf, "%u", &input) != 1)
                return -EINVAL;
 
        mutex_lock(&intel_pstate_driver_lock);
 
        if (!intel_pstate_driver) {
-               mutex_unlock(&intel_pstate_driver_lock);
-               return -EAGAIN;
+               count = -EAGAIN;
+               goto unlock_driver;
        }
 
-       mutex_lock(&intel_pstate_limits_lock);
+       no_turbo = !!clamp_t(int, input, 0, 1);
+
+       if (no_turbo == global.no_turbo)
+               goto unlock_driver;
 
-       update_turbo_state();
        if (global.turbo_disabled) {
                pr_notice_once("Turbo disabled by BIOS or unavailable on processor\n");
-               mutex_unlock(&intel_pstate_limits_lock);
-               mutex_unlock(&intel_pstate_driver_lock);
-               return -EPERM;
+               count = -EPERM;
+               goto unlock_driver;
        }
 
-       global.no_turbo = clamp_t(int, input, 0, 1);
+       WRITE_ONCE(global.no_turbo, no_turbo);
 
-       if (global.no_turbo) {
+       mutex_lock(&intel_pstate_limits_lock);
+
+       if (no_turbo) {
                struct cpudata *cpu = all_cpu_data[0];
                int pct = cpu->pstate.max_pstate * 100 / cpu->pstate.turbo_pstate;
 
@@ -1338,9 +1325,10 @@ static ssize_t store_no_turbo(struct kobject *a, struct kobj_attribute *b,
 
        mutex_unlock(&intel_pstate_limits_lock);
 
-       intel_pstate_update_policies();
-       arch_set_max_freq_ratio(global.no_turbo);
+       intel_pstate_update_limits_for_all();
+       arch_set_max_freq_ratio(no_turbo);
 
+unlock_driver:
        mutex_unlock(&intel_pstate_driver_lock);
 
        return count;
@@ -1621,7 +1609,6 @@ static void intel_pstate_notify_work(struct work_struct *work)
        struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpudata->cpu);
 
        if (policy) {
-               intel_pstate_get_hwp_cap(cpudata);
                __intel_pstate_update_max_freq(cpudata, policy);
 
                cpufreq_cpu_release(policy);
@@ -1636,11 +1623,10 @@ static cpumask_t hwp_intr_enable_mask;
 void notify_hwp_interrupt(void)
 {
        unsigned int this_cpu = smp_processor_id();
-       struct cpudata *cpudata;
        unsigned long flags;
        u64 value;
 
-       if (!READ_ONCE(hwp_active) || !boot_cpu_has(X86_FEATURE_HWP_NOTIFY))
+       if (!hwp_active || !boot_cpu_has(X86_FEATURE_HWP_NOTIFY))
                return;
 
        rdmsrl_safe(MSR_HWP_STATUS, &value);
@@ -1652,24 +1638,8 @@ void notify_hwp_interrupt(void)
        if (!cpumask_test_cpu(this_cpu, &hwp_intr_enable_mask))
                goto ack_intr;
 
-       /*
-        * Currently we never free all_cpu_data. And we can't reach here
-        * without this allocated. But for safety for future changes, added
-        * check.
-        */
-       if (unlikely(!READ_ONCE(all_cpu_data)))
-               goto ack_intr;
-
-       /*
-        * The free is done during cleanup, when cpufreq registry is failed.
-        * We wouldn't be here if it fails on init or switch status. But for
-        * future changes, added check.
-        */
-       cpudata = READ_ONCE(all_cpu_data[this_cpu]);
-       if (unlikely(!cpudata))
-               goto ack_intr;
-
-       schedule_delayed_work(&cpudata->hwp_notify_work, msecs_to_jiffies(10));
+       schedule_delayed_work(&all_cpu_data[this_cpu]->hwp_notify_work,
+                             msecs_to_jiffies(10));
 
        spin_unlock_irqrestore(&hwp_notify_lock, flags);
 
@@ -1682,7 +1652,7 @@ ack_intr:
 
 static void intel_pstate_disable_hwp_interrupt(struct cpudata *cpudata)
 {
-       unsigned long flags;
+       bool cancel_work;
 
        if (!boot_cpu_has(X86_FEATURE_HWP_NOTIFY))
                return;
@@ -1690,22 +1660,22 @@ static void intel_pstate_disable_hwp_interrupt(struct cpudata *cpudata)
        /* wrmsrl_on_cpu has to be outside spinlock as this can result in IPC */
        wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x00);
 
-       spin_lock_irqsave(&hwp_notify_lock, flags);
-       if (cpumask_test_and_clear_cpu(cpudata->cpu, &hwp_intr_enable_mask))
-               cancel_delayed_work(&cpudata->hwp_notify_work);
-       spin_unlock_irqrestore(&hwp_notify_lock, flags);
+       spin_lock_irq(&hwp_notify_lock);
+       cancel_work = cpumask_test_and_clear_cpu(cpudata->cpu, &hwp_intr_enable_mask);
+       spin_unlock_irq(&hwp_notify_lock);
+
+       if (cancel_work)
+               cancel_delayed_work_sync(&cpudata->hwp_notify_work);
 }
 
 static void intel_pstate_enable_hwp_interrupt(struct cpudata *cpudata)
 {
        /* Enable HWP notification interrupt for guaranteed performance change */
        if (boot_cpu_has(X86_FEATURE_HWP_NOTIFY)) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&hwp_notify_lock, flags);
+               spin_lock_irq(&hwp_notify_lock);
                INIT_DELAYED_WORK(&cpudata->hwp_notify_work, intel_pstate_notify_work);
                cpumask_set_cpu(cpudata->cpu, &hwp_intr_enable_mask);
-               spin_unlock_irqrestore(&hwp_notify_lock, flags);
+               spin_unlock_irq(&hwp_notify_lock);
 
                /* wrmsrl_on_cpu has to be outside spinlock as this can result in IPC */
                wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x01);
@@ -1791,7 +1761,7 @@ static u64 atom_get_val(struct cpudata *cpudata, int pstate)
        u32 vid;
 
        val = (u64)pstate << 8;
-       if (global.no_turbo && !global.turbo_disabled)
+       if (READ_ONCE(global.no_turbo) && !global.turbo_disabled)
                val |= (u64)1 << 32;
 
        vid_fp = cpudata->vid.min + mul_fp(
@@ -1956,7 +1926,7 @@ static u64 core_get_val(struct cpudata *cpudata, int pstate)
        u64 val;
 
        val = (u64)pstate << 8;
-       if (global.no_turbo && !global.turbo_disabled)
+       if (READ_ONCE(global.no_turbo) && !global.turbo_disabled)
                val |= (u64)1 << 32;
 
        return val;
@@ -2029,14 +1999,6 @@ static void intel_pstate_set_min_pstate(struct cpudata *cpu)
        intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate);
 }
 
-static void intel_pstate_max_within_limits(struct cpudata *cpu)
-{
-       int pstate = max(cpu->pstate.min_pstate, cpu->max_perf_ratio);
-
-       update_turbo_state();
-       intel_pstate_set_pstate(cpu, pstate);
-}
-
 static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
 {
        int perf_ctl_max_phys = pstate_funcs.get_max_physical(cpu->cpu);
@@ -2262,7 +2224,7 @@ static inline int32_t get_target_pstate(struct cpudata *cpu)
 
        sample->busy_scaled = busy_frac * 100;
 
-       target = global.no_turbo || global.turbo_disabled ?
+       target = READ_ONCE(global.no_turbo) ?
                        cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
        target += target >> 2;
        target = mul_fp(target, busy_frac);
@@ -2306,8 +2268,6 @@ static void intel_pstate_adjust_pstate(struct cpudata *cpu)
        struct sample *sample;
        int target_pstate;
 
-       update_turbo_state();
-
        target_pstate = get_target_pstate(cpu);
        target_pstate = intel_pstate_prepare_request(cpu, target_pstate);
        trace_cpu_frequency(target_pstate * cpu->pstate.scaling, cpu->cpu);
@@ -2437,6 +2397,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
 
+#ifdef CONFIG_ACPI
 static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] __initconst = {
        X86_MATCH(BROADWELL_D,          core_funcs),
        X86_MATCH(BROADWELL_X,          core_funcs),
@@ -2445,6 +2406,7 @@ static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] __initconst = {
        X86_MATCH(SAPPHIRERAPIDS_X,     core_funcs),
        {}
 };
+#endif
 
 static const struct x86_cpu_id intel_pstate_cpu_ee_disable_ids[] = {
        X86_MATCH(KABYLAKE,             core_funcs),
@@ -2526,7 +2488,7 @@ static void intel_pstate_clear_update_util_hook(unsigned int cpu)
 
 static int intel_pstate_get_max_freq(struct cpudata *cpu)
 {
-       return global.turbo_disabled || global.no_turbo ?
+       return READ_ONCE(global.no_turbo) ?
                        cpu->pstate.max_freq : cpu->pstate.turbo_freq;
 }
 
@@ -2611,12 +2573,14 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
        intel_pstate_update_perf_limits(cpu, policy->min, policy->max);
 
        if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) {
+               int pstate = max(cpu->pstate.min_pstate, cpu->max_perf_ratio);
+
                /*
                 * NOHZ_FULL CPUs need this as the governor callback may not
                 * be invoked on them.
                 */
                intel_pstate_clear_update_util_hook(policy->cpu);
-               intel_pstate_max_within_limits(cpu);
+               intel_pstate_set_pstate(cpu, pstate);
        } else {
                intel_pstate_set_update_util_hook(policy->cpu);
        }
@@ -2659,10 +2623,9 @@ static void intel_pstate_verify_cpu_policy(struct cpudata *cpu,
 {
        int max_freq;
 
-       update_turbo_state();
        if (hwp_active) {
                intel_pstate_get_hwp_cap(cpu);
-               max_freq = global.no_turbo || global.turbo_disabled ?
+               max_freq = READ_ONCE(global.no_turbo) ?
                                cpu->pstate.max_freq : cpu->pstate.turbo_freq;
        } else {
                max_freq = intel_pstate_get_max_freq(cpu);
@@ -2756,9 +2719,7 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
 
        /* cpuinfo and default policy values */
        policy->cpuinfo.min_freq = cpu->pstate.min_freq;
-       update_turbo_state();
-       global.turbo_disabled_mf = global.turbo_disabled;
-       policy->cpuinfo.max_freq = global.turbo_disabled ?
+       policy->cpuinfo.max_freq = READ_ONCE(global.no_turbo) ?
                        cpu->pstate.max_freq : cpu->pstate.turbo_freq;
 
        policy->min = policy->cpuinfo.min_freq;
@@ -2923,8 +2884,6 @@ static int intel_cpufreq_target(struct cpufreq_policy *policy,
        struct cpufreq_freqs freqs;
        int target_pstate;
 
-       update_turbo_state();
-
        freqs.old = policy->cur;
        freqs.new = target_freq;
 
@@ -2946,8 +2905,6 @@ static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy,
        struct cpudata *cpu = all_cpu_data[policy->cpu];
        int target_pstate;
 
-       update_turbo_state();
-
        target_pstate = intel_pstate_freq_to_hwp(cpu, target_freq);
 
        target_pstate = intel_cpufreq_update_pstate(policy, target_pstate, true);
@@ -2965,9 +2922,9 @@ static void intel_cpufreq_adjust_perf(unsigned int cpunum,
        int old_pstate = cpu->pstate.current_pstate;
        int cap_pstate, min_pstate, max_pstate, target_pstate;
 
-       update_turbo_state();
-       cap_pstate = global.turbo_disabled ? HWP_GUARANTEED_PERF(hwp_cap) :
-                                            HWP_HIGHEST_PERF(hwp_cap);
+       cap_pstate = READ_ONCE(global.no_turbo) ?
+                                       HWP_GUARANTEED_PERF(hwp_cap) :
+                                       HWP_HIGHEST_PERF(hwp_cap);
 
        /* Optimization: Avoid unnecessary divisions. */
 
@@ -3135,10 +3092,8 @@ static void intel_pstate_driver_cleanup(void)
                        if (intel_pstate_driver == &intel_pstate)
                                intel_pstate_clear_update_util_hook(cpu);
 
-                       spin_lock(&hwp_notify_lock);
                        kfree(all_cpu_data[cpu]);
                        WRITE_ONCE(all_cpu_data[cpu], NULL);
-                       spin_unlock(&hwp_notify_lock);
                }
        }
        cpus_read_unlock();
@@ -3155,6 +3110,10 @@ static int intel_pstate_register_driver(struct cpufreq_driver *driver)
 
        memset(&global, 0, sizeof(global));
        global.max_perf_pct = 100;
+       global.turbo_disabled = turbo_is_disabled();
+       global.no_turbo = global.turbo_disabled;
+
+       arch_set_max_freq_ratio(global.turbo_disabled);
 
        intel_pstate_driver = driver;
        ret = cpufreq_register_driver(intel_pstate_driver);
@@ -3466,7 +3425,7 @@ static int __init intel_pstate_init(void)
                 * deal with it.
                 */
                if ((!no_hwp && boot_cpu_has(X86_FEATURE_HWP_EPP)) || hwp_forced) {
-                       WRITE_ONCE(hwp_active, 1);
+                       hwp_active = true;
                        hwp_mode_bdw = id->driver_data;
                        intel_pstate.attr = hwp_cpufreq_attrs;
                        intel_cpufreq.attr = hwp_cpufreq_attrs;
index a0a61919bc4c16a2fecb3406244067f94a8a0cbe..518606adf14e03c41d8d0125c64c521dc656e306 100644 (file)
@@ -707,6 +707,15 @@ static const struct mtk_cpufreq_platform_data mt7623_platform_data = {
        .ccifreq_supported = false,
 };
 
+static const struct mtk_cpufreq_platform_data mt7988_platform_data = {
+       .min_volt_shift = 100000,
+       .max_volt_shift = 200000,
+       .proc_max_volt = 900000,
+       .sram_min_volt = 0,
+       .sram_max_volt = 1150000,
+       .ccifreq_supported = true,
+};
+
 static const struct mtk_cpufreq_platform_data mt8183_platform_data = {
        .min_volt_shift = 100000,
        .max_volt_shift = 200000,
@@ -740,6 +749,7 @@ static const struct of_device_id mtk_cpufreq_machines[] __initconst = {
        { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data },
        { .compatible = "mediatek,mt7622", .data = &mt7622_platform_data },
        { .compatible = "mediatek,mt7623", .data = &mt7623_platform_data },
+       { .compatible = "mediatek,mt7988a", .data = &mt7988_platform_data },
        { .compatible = "mediatek,mt8167", .data = &mt8516_platform_data },
        { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data },
        { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data },
index 32a9c88f8ff6d0a27777b68363d2417afe7fa912..0b882765cd66f7759c13c387550fc94189ae163f 100644 (file)
@@ -10,6 +10,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/arm-smccc.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
 #include <linux/nvmem-consumer.h>
 #include <linux/pm_opp.h>
 #include <linux/slab.h>
 
-#define MAX_NAME_LEN   7
-
 #define NVMEM_MASK     0x7
 #define NVMEM_SHIFT    5
 
 static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev;
 
+struct sunxi_cpufreq_data {
+       u32 (*efuse_xlate)(u32 speedbin);
+};
+
+static u32 sun50i_h6_efuse_xlate(u32 speedbin)
+{
+       u32 efuse_value;
+
+       efuse_value = (speedbin >> NVMEM_SHIFT) & NVMEM_MASK;
+
+       /*
+        * We treat unexpected efuse values as if the SoC was from
+        * the slowest bin. Expected efuse values are 1-3, slowest
+        * to fastest.
+        */
+       if (efuse_value >= 1 && efuse_value <= 3)
+               return efuse_value - 1;
+       else
+               return 0;
+}
+
+static int get_soc_id_revision(void)
+{
+#ifdef CONFIG_HAVE_ARM_SMCCC_DISCOVERY
+       return arm_smccc_get_soc_id_revision();
+#else
+       return SMCCC_RET_NOT_SUPPORTED;
+#endif
+}
+
+/*
+ * Judging by the OPP tables in the vendor BSP, the quality order of the
+ * returned speedbin index is 4 -> 0/2 -> 3 -> 1, from worst to best.
+ * 0 and 2 seem identical from the OPP tables' point of view.
+ */
+static u32 sun50i_h616_efuse_xlate(u32 speedbin)
+{
+       int ver_bits = get_soc_id_revision();
+       u32 value = 0;
+
+       switch (speedbin & 0xffff) {
+       case 0x2000:
+               value = 0;
+               break;
+       case 0x2400:
+       case 0x7400:
+       case 0x2c00:
+       case 0x7c00:
+               if (ver_bits != SMCCC_RET_NOT_SUPPORTED && ver_bits <= 1) {
+                       /* ic version A/B */
+                       value = 1;
+               } else {
+                       /* ic version C and later version */
+                       value = 2;
+               }
+               break;
+       case 0x5000:
+       case 0x5400:
+       case 0x6000:
+               value = 3;
+               break;
+       case 0x5c00:
+               value = 4;
+               break;
+       case 0x5d00:
+               value = 0;
+               break;
+       default:
+               pr_warn("sun50i-cpufreq-nvmem: unknown speed bin 0x%x, using default bin 0\n",
+                       speedbin & 0xffff);
+               value = 0;
+               break;
+       }
+
+       return value;
+}
+
+static struct sunxi_cpufreq_data sun50i_h6_cpufreq_data = {
+       .efuse_xlate = sun50i_h6_efuse_xlate,
+};
+
+static struct sunxi_cpufreq_data sun50i_h616_cpufreq_data = {
+       .efuse_xlate = sun50i_h616_efuse_xlate,
+};
+
+static const struct of_device_id cpu_opp_match_list[] = {
+       { .compatible = "allwinner,sun50i-h6-operating-points",
+         .data = &sun50i_h6_cpufreq_data,
+       },
+       { .compatible = "allwinner,sun50i-h616-operating-points",
+         .data = &sun50i_h616_cpufreq_data,
+       },
+       {}
+};
+
+/**
+ * dt_has_supported_hw() - Check if any OPPs use opp-supported-hw
+ *
+ * If we ask the cpufreq framework to use the opp-supported-hw feature, it
+ * will ignore every OPP node without that DT property. If none of the OPPs
+ * have it, the driver will fail probing, due to the lack of OPPs.
+ *
+ * Returns true if we have at least one OPP with the opp-supported-hw property.
+ */
+static bool dt_has_supported_hw(void)
+{
+       bool has_opp_supported_hw = false;
+       struct device_node *np, *opp;
+       struct device *cpu_dev;
+
+       cpu_dev = get_cpu_device(0);
+       if (!cpu_dev)
+               return false;
+
+       np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
+       if (!np)
+               return false;
+
+       for_each_child_of_node(np, opp) {
+               if (of_find_property(opp, "opp-supported-hw", NULL)) {
+                       has_opp_supported_hw = true;
+                       break;
+               }
+       }
+
+       of_node_put(np);
+
+       return has_opp_supported_hw;
+}
+
 /**
  * sun50i_cpufreq_get_efuse() - Determine speed grade from efuse value
- * @versions: Set to the value parsed from efuse
  *
- * Returns 0 if success.
+ * Returns non-negative speed bin index on success, a negative error
+ * value otherwise.
  */
-static int sun50i_cpufreq_get_efuse(u32 *versions)
+static int sun50i_cpufreq_get_efuse(void)
 {
+       const struct sunxi_cpufreq_data *opp_data;
        struct nvmem_cell *speedbin_nvmem;
+       const struct of_device_id *match;
        struct device_node *np;
        struct device *cpu_dev;
-       u32 *speedbin, efuse_value;
-       size_t len;
+       u32 *speedbin;
        int ret;
 
        cpu_dev = get_cpu_device(0);
@@ -48,12 +178,12 @@ static int sun50i_cpufreq_get_efuse(u32 *versions)
        if (!np)
                return -ENOENT;
 
-       ret = of_device_is_compatible(np,
-                                     "allwinner,sun50i-h6-operating-points");
-       if (!ret) {
+       match = of_match_node(cpu_opp_match_list, np);
+       if (!match) {
                of_node_put(np);
                return -ENOENT;
        }
+       opp_data = match->data;
 
        speedbin_nvmem = of_nvmem_cell_get(np, NULL);
        of_node_put(np);
@@ -61,33 +191,25 @@ static int sun50i_cpufreq_get_efuse(u32 *versions)
                return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
                                     "Could not get nvmem cell\n");
 
-       speedbin = nvmem_cell_read(speedbin_nvmem, &len);
+       speedbin = nvmem_cell_read(speedbin_nvmem, NULL);
        nvmem_cell_put(speedbin_nvmem);
        if (IS_ERR(speedbin))
                return PTR_ERR(speedbin);
 
-       efuse_value = (*speedbin >> NVMEM_SHIFT) & NVMEM_MASK;
-
-       /*
-        * We treat unexpected efuse values as if the SoC was from
-        * the slowest bin. Expected efuse values are 1-3, slowest
-        * to fastest.
-        */
-       if (efuse_value >= 1 && efuse_value <= 3)
-               *versions = efuse_value - 1;
-       else
-               *versions = 0;
+       ret = opp_data->efuse_xlate(*speedbin);
 
        kfree(speedbin);
-       return 0;
+
+       return ret;
 };
 
 static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
 {
        int *opp_tokens;
-       char name[MAX_NAME_LEN];
-       unsigned int cpu;
-       u32 speed = 0;
+       char name[] = "speedXXXXXXXXXXX"; /* Integers can take 11 chars max */
+       unsigned int cpu, supported_hw;
+       struct dev_pm_opp_config config = {};
+       int speed;
        int ret;
 
        opp_tokens = kcalloc(num_possible_cpus(), sizeof(*opp_tokens),
@@ -95,13 +217,24 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
        if (!opp_tokens)
                return -ENOMEM;
 
-       ret = sun50i_cpufreq_get_efuse(&speed);
-       if (ret) {
+       speed = sun50i_cpufreq_get_efuse();
+       if (speed < 0) {
                kfree(opp_tokens);
-               return ret;
+               return speed;
        }
 
-       snprintf(name, MAX_NAME_LEN, "speed%d", speed);
+       /*
+        * We need at least one OPP with the "opp-supported-hw" property,
+        * or else the upper layers will ignore every OPP and will bail out.
+        */
+       if (dt_has_supported_hw()) {
+               supported_hw = 1U << speed;
+               config.supported_hw = &supported_hw;
+               config.supported_hw_count = 1;
+       }
+
+       snprintf(name, sizeof(name), "speed%d", speed);
+       config.prop_name = name;
 
        for_each_possible_cpu(cpu) {
                struct device *cpu_dev = get_cpu_device(cpu);
@@ -111,12 +244,11 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
                        goto free_opp;
                }
 
-               opp_tokens[cpu] = dev_pm_opp_set_prop_name(cpu_dev, name);
-               if (opp_tokens[cpu] < 0) {
-                       ret = opp_tokens[cpu];
-                       pr_err("Failed to set prop name\n");
+               ret = dev_pm_opp_set_config(cpu_dev, &config);
+               if (ret < 0)
                        goto free_opp;
-               }
+
+               opp_tokens[cpu] = ret;
        }
 
        cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
@@ -131,7 +263,7 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
 
 free_opp:
        for_each_possible_cpu(cpu)
-               dev_pm_opp_put_prop_name(opp_tokens[cpu]);
+               dev_pm_opp_clear_config(opp_tokens[cpu]);
        kfree(opp_tokens);
 
        return ret;
@@ -145,7 +277,7 @@ static void sun50i_cpufreq_nvmem_remove(struct platform_device *pdev)
        platform_device_unregister(cpufreq_dt_pdev);
 
        for_each_possible_cpu(cpu)
-               dev_pm_opp_put_prop_name(opp_tokens[cpu]);
+               dev_pm_opp_clear_config(opp_tokens[cpu]);
 
        kfree(opp_tokens);
 }
@@ -160,6 +292,9 @@ static struct platform_driver sun50i_cpufreq_driver = {
 
 static const struct of_device_id sun50i_cpufreq_match_list[] = {
        { .compatible = "allwinner,sun50i-h6" },
+       { .compatible = "allwinner,sun50i-h616" },
+       { .compatible = "allwinner,sun50i-h618" },
+       { .compatible = "allwinner,sun50i-h700" },
        {}
 };
 MODULE_DEVICE_TABLE(of, sun50i_cpufreq_match_list);
index aae951d4e77cfd0136564f5f8e3ad60d1f694e3b..514146d98bca2d8aa59980a14dff3487cd8045f6 100644 (file)
@@ -52,12 +52,15 @@ out:
 
 static int tegra124_cpufreq_probe(struct platform_device *pdev)
 {
+       struct device_node *np __free(device_node) = of_cpu_device_node_get(0);
        struct tegra124_cpufreq_priv *priv;
-       struct device_node *np;
        struct device *cpu_dev;
        struct platform_device_info cpufreq_dt_devinfo = {};
        int ret;
 
+       if (!np)
+               return -ENODEV;
+
        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
@@ -66,15 +69,9 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev)
        if (!cpu_dev)
                return -ENODEV;
 
-       np = of_cpu_device_node_get(0);
-       if (!np)
-               return -ENODEV;
-
        priv->cpu_clk = of_clk_get_by_name(np, "cpu_g");
-       if (IS_ERR(priv->cpu_clk)) {
-               ret = PTR_ERR(priv->cpu_clk);
-               goto out_put_np;
-       }
+       if (IS_ERR(priv->cpu_clk))
+               return PTR_ERR(priv->cpu_clk);
 
        priv->dfll_clk = of_clk_get_by_name(np, "dfll");
        if (IS_ERR(priv->dfll_clk)) {
@@ -110,8 +107,6 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, priv);
 
-       of_node_put(np);
-
        return 0;
 
 out_put_pllp_clk:
@@ -122,8 +117,6 @@ out_put_dfll_clk:
        clk_put(priv->dfll_clk);
 out_put_cpu_clk:
        clk_put(priv->cpu_clk);
-out_put_np:
-       of_node_put(np);
 
        return ret;
 }
index 46c41e2ca727bc071214347f23149780b8e6a272..714ed53753fa57f33db233ceb15e92b203e3986f 100644 (file)
@@ -347,12 +347,10 @@ static const struct of_device_id ti_cpufreq_of_match[] = {
 
 static const struct of_device_id *ti_cpufreq_match_node(void)
 {
-       struct device_node *np;
+       struct device_node *np __free(device_node) = of_find_node_by_path("/");
        const struct of_device_id *match;
 
-       np = of_find_node_by_path("/");
        match = of_match_node(ti_cpufreq_of_match, np);
-       of_node_put(np);
 
        return match;
 }
index 13bf743f885b6c794b2d4c422a97f6d9c007a4b2..602c4dfdd7e2ead6bc1d44efe3185d2baf7d6cee 100644 (file)
@@ -59,15 +59,14 @@ static int kirkwood_cpuidle_probe(struct platform_device *pdev)
        return cpuidle_register(&kirkwood_idle_driver, NULL);
 }
 
-static int kirkwood_cpuidle_remove(struct platform_device *pdev)
+static void kirkwood_cpuidle_remove(struct platform_device *pdev)
 {
        cpuidle_unregister(&kirkwood_idle_driver);
-       return 0;
 }
 
 static struct platform_driver kirkwood_cpuidle_driver = {
        .probe = kirkwood_cpuidle_probe,
-       .remove = kirkwood_cpuidle_remove,
+       .remove_new = kirkwood_cpuidle_remove,
        .driver = {
                   .name = "kirkwood_cpuidle",
                   },
index 8e9058c4ea63e1217ad33d2f61dd8e768187af0a..6617eb494a110c0642b1899163574d2f47223fa4 100644 (file)
@@ -44,6 +44,7 @@ static DEFINE_PER_CPU(struct ladder_device, ladder_devices);
 
 /**
  * ladder_do_selection - prepares private data for a state change
+ * @dev: the CPU
  * @ldev: the ladder device
  * @old_idx: the current state index
  * @new_idx: the new target state index
index f0f54aeccc872b50311a14958ddf874860af7982..65185c9fa00134e4ed9f5449628ae04f053ba927 100644 (file)
@@ -946,25 +946,22 @@ static void cxl_mem_get_records_log(struct cxl_memdev_state *mds,
        struct cxl_memdev *cxlmd = mds->cxlds.cxlmd;
        struct device *dev = mds->cxlds.dev;
        struct cxl_get_event_payload *payload;
-       struct cxl_mbox_cmd mbox_cmd;
        u8 log_type = type;
        u16 nr_rec;
 
        mutex_lock(&mds->event.log_lock);
        payload = mds->event.buf;
 
-       mbox_cmd = (struct cxl_mbox_cmd) {
-               .opcode = CXL_MBOX_OP_GET_EVENT_RECORD,
-               .payload_in = &log_type,
-               .size_in = sizeof(log_type),
-               .payload_out = payload,
-               .min_out = struct_size(payload, records, 0),
-       };
-
        do {
                int rc, i;
-
-               mbox_cmd.size_out = mds->payload_size;
+               struct cxl_mbox_cmd mbox_cmd = (struct cxl_mbox_cmd) {
+                       .opcode = CXL_MBOX_OP_GET_EVENT_RECORD,
+                       .payload_in = &log_type,
+                       .size_in = sizeof(log_type),
+                       .payload_out = payload,
+                       .size_out = mds->payload_size,
+                       .min_out = struct_size(payload, records, 0),
+               };
 
                rc = cxl_internal_send_cmd(mds, &mbox_cmd);
                if (rc) {
@@ -1297,7 +1294,6 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
        struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
        struct cxl_mbox_poison_out *po;
        struct cxl_mbox_poison_in pi;
-       struct cxl_mbox_cmd mbox_cmd;
        int nr_records = 0;
        int rc;
 
@@ -1309,16 +1305,16 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
        pi.offset = cpu_to_le64(offset);
        pi.length = cpu_to_le64(len / CXL_POISON_LEN_MULT);
 
-       mbox_cmd = (struct cxl_mbox_cmd) {
-               .opcode = CXL_MBOX_OP_GET_POISON,
-               .size_in = sizeof(pi),
-               .payload_in = &pi,
-               .size_out = mds->payload_size,
-               .payload_out = po,
-               .min_out = struct_size(po, record, 0),
-       };
-
        do {
+               struct cxl_mbox_cmd mbox_cmd = (struct cxl_mbox_cmd){
+                       .opcode = CXL_MBOX_OP_GET_POISON,
+                       .size_in = sizeof(pi),
+                       .payload_in = &pi,
+                       .size_out = mds->payload_size,
+                       .payload_out = po,
+                       .min_out = struct_size(po, record, 0),
+               };
+
                rc = cxl_internal_send_cmd(mds, &mbox_cmd);
                if (rc)
                        break;
index 762783bb091afc8a40883c9ab2ee9c0f39e37219..887ed6e358fb9f6c77fcb9ba9424342df4e03579 100644 (file)
@@ -2184,6 +2184,7 @@ static bool parent_port_is_cxl_root(struct cxl_port *port)
 int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
                                      struct access_coordinate *coord)
 {
+       struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
        struct access_coordinate c[] = {
                {
                        .read_bandwidth = UINT_MAX,
@@ -2197,12 +2198,20 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
        struct cxl_port *iter = port;
        struct cxl_dport *dport;
        struct pci_dev *pdev;
+       struct device *dev;
        unsigned int bw;
        bool is_cxl_root;
 
        if (!is_cxl_endpoint(port))
                return -EINVAL;
 
+       /*
+        * Skip calculation for RCD. Expectation is HMAT already covers RCD case
+        * since RCH does not support hotplug.
+        */
+       if (cxlmd->cxlds->rcd)
+               return 0;
+
        /*
         * Exit the loop when the parent port of the current iter port is cxl
         * root. The iterative loop starts at the endpoint and gathers the
@@ -2232,8 +2241,12 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
                return -EINVAL;
        cxl_coordinates_combine(c, c, dport->coord);
 
+       dev = port->uport_dev->parent;
+       if (!dev_is_pci(dev))
+               return -ENODEV;
+
        /* Get the calculated PCI paths bandwidth */
-       pdev = to_pci_dev(port->uport_dev->parent);
+       pdev = to_pci_dev(dev);
        bw = pcie_bandwidth_available(pdev, NULL, NULL, NULL);
        if (bw == 0)
                return -ENXIO;
index c1cc23bcb995ccd4929a34eb554c2022543e9409..5edc522f715c3e1e1cd334cc66dae5f5ab9018a6 100644 (file)
@@ -275,18 +275,16 @@ static int exynos_nocp_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int exynos_nocp_remove(struct platform_device *pdev)
+static void exynos_nocp_remove(struct platform_device *pdev)
 {
        struct exynos_nocp *nocp = platform_get_drvdata(pdev);
 
        clk_disable_unprepare(nocp->clk);
-
-       return 0;
 }
 
 static struct platform_driver exynos_nocp_driver = {
        .probe  = exynos_nocp_probe,
-       .remove = exynos_nocp_remove,
+       .remove_new = exynos_nocp_remove,
        .driver = {
                .name   = "exynos-nocp",
                .of_match_table = exynos_nocp_id_match,
index 56bac4702006a29043f927a0ca50b89eb7448bf4..7002df20a49eef308f5f4d4aa6853e23b510b6cf 100644 (file)
@@ -692,18 +692,16 @@ static int exynos_ppmu_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int exynos_ppmu_remove(struct platform_device *pdev)
+static void exynos_ppmu_remove(struct platform_device *pdev)
 {
        struct exynos_ppmu *info = platform_get_drvdata(pdev);
 
        clk_disable_unprepare(info->ppmu.clk);
-
-       return 0;
 }
 
 static struct platform_driver exynos_ppmu_driver = {
        .probe  = exynos_ppmu_probe,
-       .remove = exynos_ppmu_remove,
+       .remove_new = exynos_ppmu_remove,
        .driver = {
                .name   = "exynos-ppmu",
                .of_match_table = exynos_ppmu_id_match,
index 245898f1a88e231a19e978361b184c1fa2f962cc..00118580905af44254021449cd009e6d66dbe995 100644 (file)
@@ -467,7 +467,6 @@ static void exynos_bus_shutdown(struct platform_device *pdev)
        devfreq_suspend_device(bus->devfreq);
 }
 
-#ifdef CONFIG_PM_SLEEP
 static int exynos_bus_resume(struct device *dev)
 {
        struct exynos_bus *bus = dev_get_drvdata(dev);
@@ -495,11 +494,9 @@ static int exynos_bus_suspend(struct device *dev)
 
        return 0;
 }
-#endif
 
-static const struct dev_pm_ops exynos_bus_pm = {
-       SET_SYSTEM_SLEEP_PM_OPS(exynos_bus_suspend, exynos_bus_resume)
-};
+static DEFINE_SIMPLE_DEV_PM_OPS(exynos_bus_pm,
+                               exynos_bus_suspend, exynos_bus_resume);
 
 static const struct of_device_id exynos_bus_of_match[] = {
        { .compatible = "samsung,exynos-bus", },
@@ -512,7 +509,7 @@ static struct platform_driver exynos_bus_platdrv = {
        .shutdown       = exynos_bus_shutdown,
        .driver = {
                .name   = "exynos-bus",
-               .pm     = &exynos_bus_pm,
+               .pm     = pm_sleep_ptr(&exynos_bus_pm),
                .of_match_table = exynos_bus_of_match,
        },
 };
index 11bc3d03494cb7366019b75556c6472634bb8e4c..7ad5225b0381d23ae518e4a6fdbe20363b74c2b6 100644 (file)
@@ -392,7 +392,7 @@ out_free_resources:
        return ret;
 }
 
-static int mtk_ccifreq_remove(struct platform_device *pdev)
+static void mtk_ccifreq_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct mtk_ccifreq_drv *drv;
@@ -405,8 +405,6 @@ static int mtk_ccifreq_remove(struct platform_device *pdev)
        regulator_disable(drv->proc_reg);
        if (drv->sram_reg)
                regulator_disable(drv->sram_reg);
-
-       return 0;
 }
 
 static const struct mtk_ccifreq_platform_data mt8183_platform_data = {
@@ -432,7 +430,7 @@ MODULE_DEVICE_TABLE(of, mtk_ccifreq_machines);
 
 static struct platform_driver mtk_ccifreq_platdrv = {
        .probe  = mtk_ccifreq_probe,
-       .remove = mtk_ccifreq_remove,
+       .remove_new = mtk_ccifreq_remove,
        .driver = {
                .name = "mtk-ccifreq",
                .of_match_table = mtk_ccifreq_machines,
index fd2c5ffedf41ee68332a438753bd11fb8382168a..d405cee92c250670e7878ebe1865c2b6b3c32a91 100644 (file)
@@ -459,13 +459,11 @@ err_edev:
        return ret;
 }
 
-static int rk3399_dmcfreq_remove(struct platform_device *pdev)
+static void rk3399_dmcfreq_remove(struct platform_device *pdev)
 {
        struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(&pdev->dev);
 
        devfreq_event_disable_edev(dmcfreq->edev);
-
-       return 0;
 }
 
 static const struct of_device_id rk3399dmc_devfreq_of_match[] = {
@@ -476,7 +474,7 @@ MODULE_DEVICE_TABLE(of, rk3399dmc_devfreq_of_match);
 
 static struct platform_driver rk3399_dmcfreq_driver = {
        .probe  = rk3399_dmcfreq_probe,
-       .remove = rk3399_dmcfreq_remove,
+       .remove_new = rk3399_dmcfreq_remove,
        .driver = {
                .name   = "rk3399-dmc-freq",
                .pm     = &rk3399_dmcfreq_pm,
index 13d32213139fb0482e235f9de06956d9226776ac..bcf654f4ff96b8c7efaa7cd2e6c5ddf9e5665807 100644 (file)
@@ -458,7 +458,7 @@ err_disable_bus:
        return dev_err_probe(dev, ret, err);
 }
 
-static int sun8i_a33_mbus_remove(struct platform_device *pdev)
+static void sun8i_a33_mbus_remove(struct platform_device *pdev)
 {
        struct sun8i_a33_mbus *priv = platform_get_drvdata(pdev);
        unsigned long initial_freq = priv->profile.initial_freq;
@@ -475,8 +475,6 @@ static int sun8i_a33_mbus_remove(struct platform_device *pdev)
        clk_rate_exclusive_put(priv->clk_mbus);
        clk_rate_exclusive_put(priv->clk_dram);
        clk_disable_unprepare(priv->clk_bus);
-
-       return 0;
 }
 
 static const struct sun8i_a33_mbus_variant sun50i_a64_mbus = {
@@ -497,7 +495,7 @@ static SIMPLE_DEV_PM_OPS(sun8i_a33_mbus_pm_ops,
 
 static struct platform_driver sun8i_a33_mbus_driver = {
        .probe  = sun8i_a33_mbus_probe,
-       .remove = sun8i_a33_mbus_remove,
+       .remove_new = sun8i_a33_mbus_remove,
        .driver = {
                .name           = "sun8i-a33-mbus",
                .of_match_table = sun8i_a33_mbus_of_match,
index 78a938969d7d76f513885d3c749392399f367256..1398814d8fbb63c3dd750a603deca0a050e488a1 100644 (file)
@@ -171,6 +171,10 @@ static irqreturn_t idma64_irq(int irq, void *dev)
        u32 status_err;
        unsigned short i;
 
+       /* Since IRQ may be shared, check if DMA controller is powered on */
+       if (status == GENMASK(31, 0))
+               return IRQ_NONE;
+
        dev_vdbg(idma64->dma.dev, "%s: status=%#x\n", __func__, status);
 
        /* Check if we have any interrupt from the DMA controller */
index 8078ab9acfbc37da0c5f633b0af9bb8529a559fe..c095a2c8f65956c696eab833f32308124dee2fd9 100644 (file)
@@ -342,7 +342,7 @@ static void idxd_cdev_evl_drain_pasid(struct idxd_wq *wq, u32 pasid)
        if (!evl)
                return;
 
-       spin_lock(&evl->lock);
+       mutex_lock(&evl->lock);
        status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
        t = status.tail;
        h = status.head;
@@ -354,9 +354,8 @@ static void idxd_cdev_evl_drain_pasid(struct idxd_wq *wq, u32 pasid)
                        set_bit(h, evl->bmap);
                h = (h + 1) % size;
        }
-       spin_unlock(&evl->lock);
-
        drain_workqueue(wq->wq);
+       mutex_unlock(&evl->lock);
 }
 
 static int idxd_cdev_release(struct inode *node, struct file *filep)
index f3f25ee676f30eb283989586d458a5c8b8c01f9f..ad4245cb301d506d7952f0a47baea171234db903 100644 (file)
@@ -66,7 +66,7 @@ static int debugfs_evl_show(struct seq_file *s, void *d)
        if (!evl || !evl->log)
                return 0;
 
-       spin_lock(&evl->lock);
+       mutex_lock(&evl->lock);
 
        evl_status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
        t = evl_status.tail;
@@ -87,7 +87,7 @@ static int debugfs_evl_show(struct seq_file *s, void *d)
                dump_event_entry(idxd, s, i, &count, processed);
        }
 
-       spin_unlock(&evl->lock);
+       mutex_unlock(&evl->lock);
        return 0;
 }
 
index ecfdf4a8f1f838ea49f1dbe3f60b15574aa8be11..c41ef195eeb9f218935520301f3582b9b6787c7d 100644 (file)
@@ -775,7 +775,7 @@ static int idxd_device_evl_setup(struct idxd_device *idxd)
                goto err_alloc;
        }
 
-       spin_lock(&evl->lock);
+       mutex_lock(&evl->lock);
        evl->log = addr;
        evl->dma = dma_addr;
        evl->log_size = size;
@@ -796,7 +796,7 @@ static int idxd_device_evl_setup(struct idxd_device *idxd)
        gencfg.evl_en = 1;
        iowrite32(gencfg.bits, idxd->reg_base + IDXD_GENCFG_OFFSET);
 
-       spin_unlock(&evl->lock);
+       mutex_unlock(&evl->lock);
        return 0;
 
 err_alloc:
@@ -819,7 +819,7 @@ static void idxd_device_evl_free(struct idxd_device *idxd)
        if (!gencfg.evl_en)
                return;
 
-       spin_lock(&evl->lock);
+       mutex_lock(&evl->lock);
        gencfg.evl_en = 0;
        iowrite32(gencfg.bits, idxd->reg_base + IDXD_GENCFG_OFFSET);
 
@@ -836,7 +836,7 @@ static void idxd_device_evl_free(struct idxd_device *idxd)
        evl_dma = evl->dma;
        evl->log = NULL;
        evl->size = IDXD_EVL_SIZE_MIN;
-       spin_unlock(&evl->lock);
+       mutex_unlock(&evl->lock);
 
        dma_free_coherent(dev, evl_log_size, evl_log, evl_dma);
 }
index a4099a1e2340fde5271e1dc29e9a5b5c224b8641..7b98944135eb440c2c5659b8e4a637085698f93c 100644 (file)
@@ -293,7 +293,7 @@ struct idxd_driver_data {
 
 struct idxd_evl {
        /* Lock to protect event log access. */
-       spinlock_t lock;
+       struct mutex lock;
        void *log;
        dma_addr_t dma;
        /* Total size of event log = number of entries * entry size. */
index 4954adc6bb609e508c510daf630f1077191fd2c7..264c4e47d7cca5651c02595652419970504e554a 100644 (file)
@@ -354,7 +354,7 @@ static int idxd_init_evl(struct idxd_device *idxd)
        if (!evl)
                return -ENOMEM;
 
-       spin_lock_init(&evl->lock);
+       mutex_init(&evl->lock);
        evl->size = IDXD_EVL_SIZE_MIN;
 
        idxd_name = dev_name(idxd_confdev(idxd));
index 348aa21389a9fceb4cd522579c8f8a9963e72ef3..8dc029c8655151a1a47d7849e6fae313c4130add 100644 (file)
@@ -363,7 +363,7 @@ static void process_evl_entries(struct idxd_device *idxd)
        evl_status.bits = 0;
        evl_status.int_pending = 1;
 
-       spin_lock(&evl->lock);
+       mutex_lock(&evl->lock);
        /* Clear interrupt pending bit */
        iowrite32(evl_status.bits_upper32,
                  idxd->reg_base + IDXD_EVLSTATUS_OFFSET + sizeof(u32));
@@ -380,7 +380,7 @@ static void process_evl_entries(struct idxd_device *idxd)
 
        evl_status.head = h;
        iowrite32(evl_status.bits_lower32, idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
-       spin_unlock(&evl->lock);
+       mutex_unlock(&evl->lock);
 }
 
 irqreturn_t idxd_misc_thread(int vec, void *data)
index fdda6d60426295baf11b191186b1d3956c1d94ae..5e94247e1ea703086365a01d1d124e5ef2acb5de 100644 (file)
@@ -528,14 +528,11 @@ static int perf_event_cpu_offline(unsigned int cpu, struct hlist_node *node)
                return 0;
 
        target = cpumask_any_but(cpu_online_mask, cpu);
-
        /* migrate events if there is a valid target */
-       if (target < nr_cpu_ids)
+       if (target < nr_cpu_ids) {
                cpumask_set_cpu(target, &perfmon_dsa_cpu_mask);
-       else
-               target = -1;
-
-       perf_pmu_migrate_context(&idxd_pmu->pmu, cpu, target);
+               perf_pmu_migrate_context(&idxd_pmu->pmu, cpu, target);
+       }
 
        return 0;
 }
index 4e76c4ec2d39660bf91d0350f0b8334e943feb3f..e001f4f7aa640fd05f76e3423ddb183f4883de4b 100644 (file)
@@ -250,7 +250,7 @@ static void pchan_update(struct owl_dma_pchan *pchan, u32 reg,
        else
                regval &= ~val;
 
-       writel(val, pchan->base + reg);
+       writel(regval, pchan->base + reg);
 }
 
 static void pchan_writel(struct owl_dma_pchan *pchan, u32 reg, u32 data)
@@ -274,7 +274,7 @@ static void dma_update(struct owl_dma *od, u32 reg, u32 val, bool state)
        else
                regval &= ~val;
 
-       writel(val, od->base + reg);
+       writel(regval, od->base + reg);
 }
 
 static void dma_writel(struct owl_dma *od, u32 reg, u32 data)
index 5f6d7f1e095f906ec22b4a4b6f67cc7309242994..ad8e3da1b2cd229ff9bdf222439c1db6d1e229ad 100644 (file)
@@ -1053,9 +1053,6 @@ static bool _trigger(struct pl330_thread *thrd)
 
        thrd->req_running = idx;
 
-       if (desc->rqtype == DMA_MEM_TO_DEV || desc->rqtype == DMA_DEV_TO_MEM)
-               UNTIL(thrd, PL330_STATE_WFP);
-
        return true;
 }
 
index 88547a23825b18aece9f4eb00221549e02eaadd1..3642508e88bb2211c13ad705bce34975945821e9 100644 (file)
@@ -746,6 +746,9 @@ static int tegra_dma_get_residual(struct tegra_dma_channel *tdc)
        bytes_xfer = dma_desc->bytes_xfer +
                     sg_req[dma_desc->sg_idx].len - (wcount * 4);
 
+       if (dma_desc->bytes_req == bytes_xfer)
+               return 0;
+
        residual = dma_desc->bytes_req - (bytes_xfer % dma_desc->bytes_req);
 
        return residual;
index 98f5f6fb9ff9c771270c64c364265f72fd7b216d..6ad08878e93862b770febb71b8bc85e66813428e 100644 (file)
@@ -117,6 +117,9 @@ struct xdma_hw_desc {
                         CHAN_CTRL_IE_WRITE_ERROR |                     \
                         CHAN_CTRL_IE_DESC_ERROR)
 
+/* bits of the channel status register */
+#define XDMA_CHAN_STATUS_BUSY                  BIT(0)
+
 #define XDMA_CHAN_STATUS_MASK CHAN_CTRL_START
 
 #define XDMA_CHAN_ERROR_MASK (CHAN_CTRL_IE_DESC_ALIGN_MISMATCH |       \
index 170017ff2aad6e58c8d0ee4ea6e7d42c15c8202c..313b217388fe95e2fd539d53c5542ce858cc25a6 100644 (file)
@@ -71,6 +71,8 @@ struct xdma_chan {
        enum dma_transfer_direction     dir;
        struct dma_slave_config         cfg;
        u32                             irq;
+       struct completion               last_interrupt;
+       bool                            stop_requested;
 };
 
 /**
@@ -376,6 +378,8 @@ static int xdma_xfer_start(struct xdma_chan *xchan)
                return ret;
 
        xchan->busy = true;
+       xchan->stop_requested = false;
+       reinit_completion(&xchan->last_interrupt);
 
        return 0;
 }
@@ -387,7 +391,6 @@ static int xdma_xfer_start(struct xdma_chan *xchan)
 static int xdma_xfer_stop(struct xdma_chan *xchan)
 {
        int ret;
-       u32 val;
        struct xdma_device *xdev = xchan->xdev_hdl;
 
        /* clear run stop bit to prevent any further auto-triggering */
@@ -395,13 +398,7 @@ static int xdma_xfer_stop(struct xdma_chan *xchan)
                           CHAN_CTRL_RUN_STOP);
        if (ret)
                return ret;
-
-       /* Clear the channel status register */
-       ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_STATUS_RC, &val);
-       if (ret)
-               return ret;
-
-       return 0;
+       return ret;
 }
 
 /**
@@ -474,6 +471,8 @@ static int xdma_alloc_channels(struct xdma_device *xdev,
                xchan->xdev_hdl = xdev;
                xchan->base = base + i * XDMA_CHAN_STRIDE;
                xchan->dir = dir;
+               xchan->stop_requested = false;
+               init_completion(&xchan->last_interrupt);
 
                ret = xdma_channel_init(xchan);
                if (ret)
@@ -521,6 +520,7 @@ static int xdma_terminate_all(struct dma_chan *chan)
        spin_lock_irqsave(&xdma_chan->vchan.lock, flags);
 
        xdma_chan->busy = false;
+       xdma_chan->stop_requested = true;
        vd = vchan_next_desc(&xdma_chan->vchan);
        if (vd) {
                list_del(&vd->node);
@@ -542,17 +542,26 @@ static int xdma_terminate_all(struct dma_chan *chan)
 static void xdma_synchronize(struct dma_chan *chan)
 {
        struct xdma_chan *xdma_chan = to_xdma_chan(chan);
+       struct xdma_device *xdev = xdma_chan->xdev_hdl;
+       int st = 0;
+
+       /* If the engine continues running, wait for the last interrupt */
+       regmap_read(xdev->rmap, xdma_chan->base + XDMA_CHAN_STATUS, &st);
+       if (st & XDMA_CHAN_STATUS_BUSY)
+               wait_for_completion_timeout(&xdma_chan->last_interrupt, msecs_to_jiffies(1000));
 
        vchan_synchronize(&xdma_chan->vchan);
 }
 
 /**
- * xdma_fill_descs - Fill hardware descriptors with contiguous memory block addresses
- * @sw_desc: tx descriptor state container
- * @src_addr: Value for a ->src_addr field of a first descriptor
- * @dst_addr: Value for a ->dst_addr field of a first descriptor
- * @size: Total size of a contiguous memory block
- * @filled_descs_num: Number of filled hardware descriptors for corresponding sw_desc
+ * xdma_fill_descs() - Fill hardware descriptors for one contiguous memory chunk.
+ *                    More than one descriptor will be used if the size is bigger
+ *                    than XDMA_DESC_BLEN_MAX.
+ * @sw_desc: Descriptor container
+ * @src_addr: First value for the ->src_addr field
+ * @dst_addr: First value for the ->dst_addr field
+ * @size: Size of the contiguous memory block
+ * @filled_descs_num: Index of the first descriptor to take care of in @sw_desc
  */
 static inline u32 xdma_fill_descs(struct xdma_desc *sw_desc, u64 src_addr,
                                  u64 dst_addr, u32 size, u32 filled_descs_num)
@@ -704,7 +713,7 @@ xdma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t address,
        desc_num = 0;
        for (i = 0; i < periods; i++) {
                desc_num += xdma_fill_descs(sw_desc, *src, *dst, period_size, desc_num);
-               addr += i * period_size;
+               addr += period_size;
        }
 
        tx_desc = vchan_tx_prep(&xdma_chan->vchan, &sw_desc->vdesc, flags);
@@ -876,6 +885,9 @@ static irqreturn_t xdma_channel_isr(int irq, void *dev_id)
        u32 st;
        bool repeat_tx;
 
+       if (xchan->stop_requested)
+               complete(&xchan->last_interrupt);
+
        spin_lock(&xchan->vchan.lock);
 
        /* get submitted request */
index b82815e64d24e8352ac025bc1bd52de497530d66..eb0637d90342a6727d28c300394e81aa6fa44b74 100644 (file)
@@ -214,7 +214,8 @@ struct xilinx_dpdma_tx_desc {
  * @running: true if the channel is running
  * @first_frame: flag for the first frame of stream
  * @video_group: flag if multi-channel operation is needed for video channels
- * @lock: lock to access struct xilinx_dpdma_chan
+ * @lock: lock to access struct xilinx_dpdma_chan. Must be taken before
+ *        @vchan.lock, if both are to be held.
  * @desc_pool: descriptor allocation pool
  * @err_task: error IRQ bottom half handler
  * @desc: References to descriptors being processed
@@ -1097,12 +1098,14 @@ static void xilinx_dpdma_chan_vsync_irq(struct  xilinx_dpdma_chan *chan)
         * Complete the active descriptor, if any, promote the pending
         * descriptor to active, and queue the next transfer, if any.
         */
+       spin_lock(&chan->vchan.lock);
        if (chan->desc.active)
                vchan_cookie_complete(&chan->desc.active->vdesc);
        chan->desc.active = pending;
        chan->desc.pending = NULL;
 
        xilinx_dpdma_chan_queue_transfer(chan);
+       spin_unlock(&chan->vchan.lock);
 
 out:
        spin_unlock_irqrestore(&chan->lock, flags);
@@ -1264,10 +1267,12 @@ static void xilinx_dpdma_issue_pending(struct dma_chan *dchan)
        struct xilinx_dpdma_chan *chan = to_xilinx_chan(dchan);
        unsigned long flags;
 
-       spin_lock_irqsave(&chan->vchan.lock, flags);
+       spin_lock_irqsave(&chan->lock, flags);
+       spin_lock(&chan->vchan.lock);
        if (vchan_issue_pending(&chan->vchan))
                xilinx_dpdma_chan_queue_transfer(chan);
-       spin_unlock_irqrestore(&chan->vchan.lock, flags);
+       spin_unlock(&chan->vchan.lock);
+       spin_unlock_irqrestore(&chan->lock, flags);
 }
 
 static int xilinx_dpdma_config(struct dma_chan *dchan,
@@ -1495,7 +1500,9 @@ static void xilinx_dpdma_chan_err_task(struct tasklet_struct *t)
                    XILINX_DPDMA_EINTR_CHAN_ERR_MASK << chan->id);
 
        spin_lock_irqsave(&chan->lock, flags);
+       spin_lock(&chan->vchan.lock);
        xilinx_dpdma_chan_queue_transfer(chan);
+       spin_unlock(&chan->vchan.lock);
        spin_unlock_irqrestore(&chan->lock, flags);
 }
 
index 64eaca80d736c5652958ddb5e21bc64ff3a6bc65..d0f6693ca142623af740bf69ee8664fc88926fcb 100644 (file)
@@ -42,6 +42,7 @@ struct dpll_pin_registration {
        struct list_head list;
        const struct dpll_pin_ops *ops;
        void *priv;
+       void *cookie;
 };
 
 struct dpll_device *dpll_device_get_by_id(int id)
@@ -54,12 +55,14 @@ struct dpll_device *dpll_device_get_by_id(int id)
 
 static struct dpll_pin_registration *
 dpll_pin_registration_find(struct dpll_pin_ref *ref,
-                          const struct dpll_pin_ops *ops, void *priv)
+                          const struct dpll_pin_ops *ops, void *priv,
+                          void *cookie)
 {
        struct dpll_pin_registration *reg;
 
        list_for_each_entry(reg, &ref->registration_list, list) {
-               if (reg->ops == ops && reg->priv == priv)
+               if (reg->ops == ops && reg->priv == priv &&
+                   reg->cookie == cookie)
                        return reg;
        }
        return NULL;
@@ -67,7 +70,8 @@ dpll_pin_registration_find(struct dpll_pin_ref *ref,
 
 static int
 dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
-                   const struct dpll_pin_ops *ops, void *priv)
+                   const struct dpll_pin_ops *ops, void *priv,
+                   void *cookie)
 {
        struct dpll_pin_registration *reg;
        struct dpll_pin_ref *ref;
@@ -78,7 +82,7 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
        xa_for_each(xa_pins, i, ref) {
                if (ref->pin != pin)
                        continue;
-               reg = dpll_pin_registration_find(ref, ops, priv);
+               reg = dpll_pin_registration_find(ref, ops, priv, cookie);
                if (reg) {
                        refcount_inc(&ref->refcount);
                        return 0;
@@ -111,6 +115,7 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
        }
        reg->ops = ops;
        reg->priv = priv;
+       reg->cookie = cookie;
        if (ref_exists)
                refcount_inc(&ref->refcount);
        list_add_tail(&reg->list, &ref->registration_list);
@@ -119,7 +124,8 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
 }
 
 static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
-                              const struct dpll_pin_ops *ops, void *priv)
+                              const struct dpll_pin_ops *ops, void *priv,
+                              void *cookie)
 {
        struct dpll_pin_registration *reg;
        struct dpll_pin_ref *ref;
@@ -128,7 +134,7 @@ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
        xa_for_each(xa_pins, i, ref) {
                if (ref->pin != pin)
                        continue;
-               reg = dpll_pin_registration_find(ref, ops, priv);
+               reg = dpll_pin_registration_find(ref, ops, priv, cookie);
                if (WARN_ON(!reg))
                        return -EINVAL;
                list_del(&reg->list);
@@ -146,7 +152,7 @@ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
 
 static int
 dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
-                    const struct dpll_pin_ops *ops, void *priv)
+                    const struct dpll_pin_ops *ops, void *priv, void *cookie)
 {
        struct dpll_pin_registration *reg;
        struct dpll_pin_ref *ref;
@@ -157,7 +163,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
        xa_for_each(xa_dplls, i, ref) {
                if (ref->dpll != dpll)
                        continue;
-               reg = dpll_pin_registration_find(ref, ops, priv);
+               reg = dpll_pin_registration_find(ref, ops, priv, cookie);
                if (reg) {
                        refcount_inc(&ref->refcount);
                        return 0;
@@ -190,6 +196,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
        }
        reg->ops = ops;
        reg->priv = priv;
+       reg->cookie = cookie;
        if (ref_exists)
                refcount_inc(&ref->refcount);
        list_add_tail(&reg->list, &ref->registration_list);
@@ -199,7 +206,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
 
 static void
 dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll,
-                    const struct dpll_pin_ops *ops, void *priv)
+                    const struct dpll_pin_ops *ops, void *priv, void *cookie)
 {
        struct dpll_pin_registration *reg;
        struct dpll_pin_ref *ref;
@@ -208,7 +215,7 @@ dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll,
        xa_for_each(xa_dplls, i, ref) {
                if (ref->dpll != dpll)
                        continue;
-               reg = dpll_pin_registration_find(ref, ops, priv);
+               reg = dpll_pin_registration_find(ref, ops, priv, cookie);
                if (WARN_ON(!reg))
                        return;
                list_del(&reg->list);
@@ -594,14 +601,14 @@ EXPORT_SYMBOL_GPL(dpll_pin_put);
 
 static int
 __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
-                   const struct dpll_pin_ops *ops, void *priv)
+                   const struct dpll_pin_ops *ops, void *priv, void *cookie)
 {
        int ret;
 
-       ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv);
+       ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv, cookie);
        if (ret)
                return ret;
-       ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv);
+       ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv, cookie);
        if (ret)
                goto ref_pin_del;
        xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED);
@@ -610,7 +617,7 @@ __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
        return ret;
 
 ref_pin_del:
-       dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv);
+       dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie);
        return ret;
 }
 
@@ -642,7 +649,7 @@ dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
                      dpll->clock_id == pin->clock_id)))
                ret = -EINVAL;
        else
-               ret = __dpll_pin_register(dpll, pin, ops, priv);
+               ret = __dpll_pin_register(dpll, pin, ops, priv, NULL);
        mutex_unlock(&dpll_lock);
 
        return ret;
@@ -651,11 +658,11 @@ EXPORT_SYMBOL_GPL(dpll_pin_register);
 
 static void
 __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
-                     const struct dpll_pin_ops *ops, void *priv)
+                     const struct dpll_pin_ops *ops, void *priv, void *cookie)
 {
        ASSERT_DPLL_PIN_REGISTERED(pin);
-       dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv);
-       dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv);
+       dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie);
+       dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie);
        if (xa_empty(&pin->dpll_refs))
                xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED);
 }
@@ -680,7 +687,7 @@ void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
 
        mutex_lock(&dpll_lock);
        dpll_pin_delete_ntf(pin);
-       __dpll_pin_unregister(dpll, pin, ops, priv);
+       __dpll_pin_unregister(dpll, pin, ops, priv, NULL);
        mutex_unlock(&dpll_lock);
 }
 EXPORT_SYMBOL_GPL(dpll_pin_unregister);
@@ -716,12 +723,12 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
                return -EINVAL;
 
        mutex_lock(&dpll_lock);
-       ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv);
+       ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv, pin);
        if (ret)
                goto unlock;
        refcount_inc(&pin->refcount);
        xa_for_each(&parent->dpll_refs, i, ref) {
-               ret = __dpll_pin_register(ref->dpll, pin, ops, priv);
+               ret = __dpll_pin_register(ref->dpll, pin, ops, priv, parent);
                if (ret) {
                        stop = i;
                        goto dpll_unregister;
@@ -735,11 +742,12 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
 dpll_unregister:
        xa_for_each(&parent->dpll_refs, i, ref)
                if (i < stop) {
-                       __dpll_pin_unregister(ref->dpll, pin, ops, priv);
+                       __dpll_pin_unregister(ref->dpll, pin, ops, priv,
+                                             parent);
                        dpll_pin_delete_ntf(pin);
                }
        refcount_dec(&pin->refcount);
-       dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv);
+       dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin);
 unlock:
        mutex_unlock(&dpll_lock);
        return ret;
@@ -764,10 +772,10 @@ void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin,
 
        mutex_lock(&dpll_lock);
        dpll_pin_delete_ntf(pin);
-       dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv);
+       dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin);
        refcount_dec(&pin->refcount);
        xa_for_each(&pin->dpll_refs, i, ref)
-               __dpll_pin_unregister(ref->dpll, pin, ops, priv);
+               __dpll_pin_unregister(ref->dpll, pin, ops, priv, parent);
        mutex_unlock(&dpll_lock);
 }
 EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister);
index 1688a5050f63a4e2754aa3b49974dd6f9bc57fa7..a556d23e8261c6df566bcccf3b538478ebba659c 100644 (file)
@@ -425,7 +425,7 @@ static void handle_error(struct mem_ctl_info *mci, struct ecc_status *stat)
                         convert_to_physical(priv, pinf), pinf.burstpos);
 
                edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
-                                    priv->ce_cnt, 0, 0, 0, 0, 0, -1,
+                                    1, 0, 0, 0, 0, 0, -1,
                                     priv->message, "");
        }
 
@@ -438,7 +438,7 @@ static void handle_error(struct mem_ctl_info *mci, struct ecc_status *stat)
                         convert_to_physical(priv, pinf), pinf.burstpos);
 
                edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
-                                    priv->ue_cnt, 0, 0, 0, 0, 0, -1,
+                                    1, 0, 0, 0, 0, 0, -1,
                                     priv->message, "");
        }
 
@@ -865,6 +865,9 @@ static ssize_t inject_data_ue_store(struct file *file, const char __user *data,
        for (i = 0; i < NUM_UE_BITPOS; i++)
                token[i] = strsep(&pbuf, ",");
 
+       if (!token[0] || !token[1])
+               return -EFAULT;
+
        ret = kstrtou8(token[0], 0, &ue0);
        if (ret)
                return ret;
@@ -1135,8 +1138,7 @@ static int mc_probe(struct platform_device *pdev)
        }
 
        rc = xlnx_register_event(PM_NOTIFY_CB, VERSAL_EVENT_ERROR_PMC_ERR1,
-                                XPM_EVENT_ERROR_MASK_DDRMC_CR | XPM_EVENT_ERROR_MASK_DDRMC_NCR |
-                                XPM_EVENT_ERROR_MASK_NOC_CR | XPM_EVENT_ERROR_MASK_NOC_NCR,
+                                XPM_EVENT_ERROR_MASK_DDRMC_CR | XPM_EVENT_ERROR_MASK_DDRMC_NCR,
                                 false, err_callback, mci);
        if (rc) {
                if (rc == -EACCES)
@@ -1173,8 +1175,6 @@ static void mc_remove(struct platform_device *pdev)
 
        xlnx_unregister_event(PM_NOTIFY_CB, VERSAL_EVENT_ERROR_PMC_ERR1,
                              XPM_EVENT_ERROR_MASK_DDRMC_CR |
-                             XPM_EVENT_ERROR_MASK_NOC_CR |
-                             XPM_EVENT_ERROR_MASK_NOC_NCR |
                              XPM_EVENT_ERROR_MASK_DDRMC_NCR, err_callback, mci);
        edac_mc_del_mc(&pdev->dev);
        edac_mc_free(mci);
index b0d671db178a85b6ab98de29f05b994db99a8697..ea31ac7ac1ca931a569af239dbaa2052448e8df5 100644 (file)
@@ -148,10 +148,12 @@ packet_buffer_get(struct client *client, char __user *data, size_t user_length)
        if (atomic_read(&buffer->size) == 0)
                return -ENODEV;
 
-       /* FIXME: Check length <= user_length. */
+       length = buffer->head->length;
+
+       if (length > user_length)
+               return 0;
 
        end = buffer->data + buffer->capacity;
-       length = buffer->head->length;
 
        if (&buffer->head->data[length] < end) {
                if (copy_to_user(data, buffer->head->data, length))
index 38d19410a2be68cab9f382d48ab7f15493c42af0..b9ae0340b8a70343185fe97364229dab4f72101c 100644 (file)
@@ -1556,6 +1556,8 @@ static int handle_at_packet(struct context *context,
 #define HEADER_GET_DATA_LENGTH(q)      (((q) >> 16) & 0xffff)
 #define HEADER_GET_EXTENDED_TCODE(q)   (((q) >> 0) & 0xffff)
 
+static u32 get_cycle_time(struct fw_ohci *ohci);
+
 static void handle_local_rom(struct fw_ohci *ohci,
                             struct fw_packet *packet, u32 csr)
 {
@@ -1580,6 +1582,8 @@ static void handle_local_rom(struct fw_ohci *ohci,
                                 (void *) ohci->config_rom + i, length);
        }
 
+       // Timestamping on behalf of the hardware.
+       response.timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci));
        fw_core_handle_response(&ohci->card, &response);
 }
 
@@ -1628,6 +1632,8 @@ static void handle_local_lock(struct fw_ohci *ohci,
        fw_fill_response(&response, packet->header, RCODE_BUSY, NULL, 0);
 
  out:
+       // Timestamping on behalf of the hardware.
+       response.timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci));
        fw_core_handle_response(&ohci->card, &response);
 }
 
@@ -1670,8 +1676,6 @@ static void handle_local_request(struct context *ctx, struct fw_packet *packet)
        }
 }
 
-static u32 get_cycle_time(struct fw_ohci *ohci);
-
 static void at_context_transmit(struct context *ctx, struct fw_packet *packet)
 {
        unsigned long flags;
index 5b439d04079c841e1bd698f63d96d1b428f6b2ed..50f6503fe49f5e44474b99a1cc53edf0fa97d283 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/memblock.h>
 #include <linux/spinlock.h>
 #include <linux/crash_dump.h>
+#include <linux/nmi.h>
 #include <asm/unaccepted_memory.h>
 
 /* Protects unaccepted memory bitmap and accepting_list */
@@ -149,6 +150,9 @@ retry:
        }
 
        list_del(&range.list);
+
+       touch_softlockup_watchdog();
+
        spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
 }
 
index 32188f098ef3497eadebab991ed956a57eb6768a..bc550ad0dbe0c7f57c05508382ae5f626ebe6db1 100644 (file)
@@ -221,6 +221,19 @@ struct qsee_rsp_uefi_query_variable_info {
  * alignment of 8 bytes (64 bits) for GUIDs. Our definition of efi_guid_t,
  * however, has an alignment of 4 byte (32 bits). So far, this seems to work
  * fine here. See also the comment on the typedef of efi_guid_t.
+ *
+ * Note: It looks like uefisecapp is quite picky about how the memory passed to
+ * it is structured and aligned. In particular the request/response setup used
+ * for QSEE_CMD_UEFI_GET_VARIABLE. While qcom_qseecom_app_send(), in theory,
+ * accepts separate buffers/addresses for the request and response parts, in
+ * practice, however, it seems to expect them to be both part of a larger
+ * contiguous block. We initially allocated separate buffers for the request
+ * and response but this caused the QSEE_CMD_UEFI_GET_VARIABLE command to
+ * either not write any response to the response buffer or outright crash the
+ * device. Therefore, we now allocate a single contiguous block of DMA memory
+ * for both and properly align the data using the macros below. In particular,
+ * request and response structs are aligned at 8 byte (via __reqdata_offs()),
+ * following the driver that this has been reverse-engineered from.
  */
 #define qcuefi_buf_align_fields(fields...)                                     \
        ({                                                                      \
@@ -244,6 +257,12 @@ struct qsee_rsp_uefi_query_variable_info {
 #define __array_offs(type, count, offset)                                      \
        __field_impl(sizeof(type) * (count), __alignof__(type), offset)
 
+#define __array_offs_aligned(type, count, align, offset)                       \
+       __field_impl(sizeof(type) * (count), align, offset)
+
+#define __reqdata_offs(size, offset)                                           \
+       __array_offs_aligned(u8, size, 8, offset)
+
 #define __array(type, count)           __array_offs(type, count, NULL)
 #define __field_offs(type, offset)     __array_offs(type, 1, offset)
 #define __field(type)                  __array_offs(type, 1, NULL)
@@ -277,10 +296,15 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
        unsigned long buffer_size = *data_size;
        efi_status_t efi_status = EFI_SUCCESS;
        unsigned long name_length;
+       dma_addr_t cmd_buf_dma;
+       size_t cmd_buf_size;
+       void *cmd_buf;
        size_t guid_offs;
        size_t name_offs;
        size_t req_size;
        size_t rsp_size;
+       size_t req_offs;
+       size_t rsp_offs;
        ssize_t status;
 
        if (!name || !guid)
@@ -304,17 +328,19 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
                __array(u8, buffer_size)
        );
 
-       req_data = kzalloc(req_size, GFP_KERNEL);
-       if (!req_data) {
+       cmd_buf_size = qcuefi_buf_align_fields(
+               __reqdata_offs(req_size, &req_offs)
+               __reqdata_offs(rsp_size, &rsp_offs)
+       );
+
+       cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
+       if (!cmd_buf) {
                efi_status = EFI_OUT_OF_RESOURCES;
                goto out;
        }
 
-       rsp_data = kzalloc(rsp_size, GFP_KERNEL);
-       if (!rsp_data) {
-               efi_status = EFI_OUT_OF_RESOURCES;
-               goto out_free_req;
-       }
+       req_data = cmd_buf + req_offs;
+       rsp_data = cmd_buf + rsp_offs;
 
        req_data->command_id = QSEE_CMD_UEFI_GET_VARIABLE;
        req_data->data_size = buffer_size;
@@ -332,7 +358,9 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
 
        memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size);
 
-       status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, rsp_size);
+       status = qcom_qseecom_app_send(qcuefi->client,
+                                      cmd_buf_dma + req_offs, req_size,
+                                      cmd_buf_dma + rsp_offs, rsp_size);
        if (status) {
                efi_status = EFI_DEVICE_ERROR;
                goto out_free;
@@ -407,9 +435,7 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
        memcpy(data, ((void *)rsp_data) + rsp_data->data_offset, rsp_data->data_size);
 
 out_free:
-       kfree(rsp_data);
-out_free_req:
-       kfree(req_data);
+       qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
 out:
        return efi_status;
 }
@@ -422,10 +448,15 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
        struct qsee_rsp_uefi_set_variable *rsp_data;
        efi_status_t efi_status = EFI_SUCCESS;
        unsigned long name_length;
+       dma_addr_t cmd_buf_dma;
+       size_t cmd_buf_size;
+       void *cmd_buf;
        size_t name_offs;
        size_t guid_offs;
        size_t data_offs;
        size_t req_size;
+       size_t req_offs;
+       size_t rsp_offs;
        ssize_t status;
 
        if (!name || !guid)
@@ -450,17 +481,19 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
                __array_offs(u8, data_size, &data_offs)
        );
 
-       req_data = kzalloc(req_size, GFP_KERNEL);
-       if (!req_data) {
+       cmd_buf_size = qcuefi_buf_align_fields(
+               __reqdata_offs(req_size, &req_offs)
+               __reqdata_offs(sizeof(*rsp_data), &rsp_offs)
+       );
+
+       cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
+       if (!cmd_buf) {
                efi_status = EFI_OUT_OF_RESOURCES;
                goto out;
        }
 
-       rsp_data = kzalloc(sizeof(*rsp_data), GFP_KERNEL);
-       if (!rsp_data) {
-               efi_status = EFI_OUT_OF_RESOURCES;
-               goto out_free_req;
-       }
+       req_data = cmd_buf + req_offs;
+       rsp_data = cmd_buf + rsp_offs;
 
        req_data->command_id = QSEE_CMD_UEFI_SET_VARIABLE;
        req_data->attributes = attributes;
@@ -483,8 +516,9 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
        if (data_size)
                memcpy(((void *)req_data) + req_data->data_offset, data, req_data->data_size);
 
-       status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data,
-                                      sizeof(*rsp_data));
+       status = qcom_qseecom_app_send(qcuefi->client,
+                                      cmd_buf_dma + req_offs, req_size,
+                                      cmd_buf_dma + rsp_offs, sizeof(*rsp_data));
        if (status) {
                efi_status = EFI_DEVICE_ERROR;
                goto out_free;
@@ -507,9 +541,7 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
        }
 
 out_free:
-       kfree(rsp_data);
-out_free_req:
-       kfree(req_data);
+       qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
 out:
        return efi_status;
 }
@@ -521,10 +553,15 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
        struct qsee_req_uefi_get_next_variable *req_data;
        struct qsee_rsp_uefi_get_next_variable *rsp_data;
        efi_status_t efi_status = EFI_SUCCESS;
+       dma_addr_t cmd_buf_dma;
+       size_t cmd_buf_size;
+       void *cmd_buf;
        size_t guid_offs;
        size_t name_offs;
        size_t req_size;
        size_t rsp_size;
+       size_t req_offs;
+       size_t rsp_offs;
        ssize_t status;
 
        if (!name_size || !name || !guid)
@@ -545,17 +582,19 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
                __array(*name, *name_size / sizeof(*name))
        );
 
-       req_data = kzalloc(req_size, GFP_KERNEL);
-       if (!req_data) {
+       cmd_buf_size = qcuefi_buf_align_fields(
+               __reqdata_offs(req_size, &req_offs)
+               __reqdata_offs(rsp_size, &rsp_offs)
+       );
+
+       cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
+       if (!cmd_buf) {
                efi_status = EFI_OUT_OF_RESOURCES;
                goto out;
        }
 
-       rsp_data = kzalloc(rsp_size, GFP_KERNEL);
-       if (!rsp_data) {
-               efi_status = EFI_OUT_OF_RESOURCES;
-               goto out_free_req;
-       }
+       req_data = cmd_buf + req_offs;
+       rsp_data = cmd_buf + rsp_offs;
 
        req_data->command_id = QSEE_CMD_UEFI_GET_NEXT_VARIABLE;
        req_data->guid_offset = guid_offs;
@@ -572,7 +611,9 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
                goto out_free;
        }
 
-       status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, rsp_size);
+       status = qcom_qseecom_app_send(qcuefi->client,
+                                      cmd_buf_dma + req_offs, req_size,
+                                      cmd_buf_dma + rsp_offs, rsp_size);
        if (status) {
                efi_status = EFI_DEVICE_ERROR;
                goto out_free;
@@ -645,9 +686,7 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
        }
 
 out_free:
-       kfree(rsp_data);
-out_free_req:
-       kfree(req_data);
+       qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
 out:
        return efi_status;
 }
@@ -659,26 +698,34 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
        struct qsee_req_uefi_query_variable_info *req_data;
        struct qsee_rsp_uefi_query_variable_info *rsp_data;
        efi_status_t efi_status = EFI_SUCCESS;
+       dma_addr_t cmd_buf_dma;
+       size_t cmd_buf_size;
+       void *cmd_buf;
+       size_t req_offs;
+       size_t rsp_offs;
        int status;
 
-       req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
-       if (!req_data) {
+       cmd_buf_size = qcuefi_buf_align_fields(
+               __reqdata_offs(sizeof(*req_data), &req_offs)
+               __reqdata_offs(sizeof(*rsp_data), &rsp_offs)
+       );
+
+       cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
+       if (!cmd_buf) {
                efi_status = EFI_OUT_OF_RESOURCES;
                goto out;
        }
 
-       rsp_data = kzalloc(sizeof(*rsp_data), GFP_KERNEL);
-       if (!rsp_data) {
-               efi_status = EFI_OUT_OF_RESOURCES;
-               goto out_free_req;
-       }
+       req_data = cmd_buf + req_offs;
+       rsp_data = cmd_buf + rsp_offs;
 
        req_data->command_id = QSEE_CMD_UEFI_QUERY_VARIABLE_INFO;
        req_data->attributes = attr;
        req_data->length = sizeof(*req_data);
 
-       status = qcom_qseecom_app_send(qcuefi->client, req_data, sizeof(*req_data), rsp_data,
-                                      sizeof(*rsp_data));
+       status = qcom_qseecom_app_send(qcuefi->client,
+                                      cmd_buf_dma + req_offs, sizeof(*req_data),
+                                      cmd_buf_dma + rsp_offs, sizeof(*rsp_data));
        if (status) {
                efi_status = EFI_DEVICE_ERROR;
                goto out_free;
@@ -711,9 +758,7 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
                *max_variable_size = rsp_data->max_variable_size;
 
 out_free:
-       kfree(rsp_data);
-out_free_req:
-       kfree(req_data);
+       qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
 out:
        return efi_status;
 }
index 520de9b5633abc5aab075400b7feb6b97dcef97c..90283f160a2286d8a12b9b0e313f1dfbbbbd9055 100644 (file)
@@ -1576,9 +1576,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_get_id);
 /**
  * qcom_scm_qseecom_app_send() - Send to and receive data from a given QSEE app.
  * @app_id:   The ID of the target app.
- * @req:      Request buffer sent to the app (must be DMA-mappable).
+ * @req:      DMA address of the request buffer sent to the app.
  * @req_size: Size of the request buffer.
- * @rsp:      Response buffer, written to by the app (must be DMA-mappable).
+ * @rsp:      DMA address of the response buffer, written to by the app.
  * @rsp_size: Size of the response buffer.
  *
  * Sends a request to the QSEE app associated with the given ID and read back
@@ -1589,33 +1589,13 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_get_id);
  *
  * Return: Zero on success, nonzero on failure.
  */
-int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size, void *rsp,
-                             size_t rsp_size)
+int qcom_scm_qseecom_app_send(u32 app_id, dma_addr_t req, size_t req_size,
+                             dma_addr_t rsp, size_t rsp_size)
 {
        struct qcom_scm_qseecom_resp res = {};
        struct qcom_scm_desc desc = {};
-       dma_addr_t req_phys;
-       dma_addr_t rsp_phys;
        int status;
 
-       /* Map request buffer */
-       req_phys = dma_map_single(__scm->dev, req, req_size, DMA_TO_DEVICE);
-       status = dma_mapping_error(__scm->dev, req_phys);
-       if (status) {
-               dev_err(__scm->dev, "qseecom: failed to map request buffer\n");
-               return status;
-       }
-
-       /* Map response buffer */
-       rsp_phys = dma_map_single(__scm->dev, rsp, rsp_size, DMA_FROM_DEVICE);
-       status = dma_mapping_error(__scm->dev, rsp_phys);
-       if (status) {
-               dma_unmap_single(__scm->dev, req_phys, req_size, DMA_TO_DEVICE);
-               dev_err(__scm->dev, "qseecom: failed to map response buffer\n");
-               return status;
-       }
-
-       /* Set up SCM call data */
        desc.owner = QSEECOM_TZ_OWNER_TZ_APPS;
        desc.svc = QSEECOM_TZ_SVC_APP_ID_PLACEHOLDER;
        desc.cmd = QSEECOM_TZ_CMD_APP_SEND;
@@ -1623,18 +1603,13 @@ int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size, void *rsp,
                                     QCOM_SCM_RW, QCOM_SCM_VAL,
                                     QCOM_SCM_RW, QCOM_SCM_VAL);
        desc.args[0] = app_id;
-       desc.args[1] = req_phys;
+       desc.args[1] = req;
        desc.args[2] = req_size;
-       desc.args[3] = rsp_phys;
+       desc.args[3] = rsp;
        desc.args[4] = rsp_size;
 
-       /* Perform call */
        status = qcom_scm_qseecom_call(&desc, &res);
 
-       /* Unmap buffers */
-       dma_unmap_single(__scm->dev, rsp_phys, rsp_size, DMA_FROM_DEVICE);
-       dma_unmap_single(__scm->dev, req_phys, req_size, DMA_TO_DEVICE);
-
        if (status)
                return status;
 
index db818f9dcb8ee7d8183eacd1a7837e1b341f9039..d670635914ecb63e84f4e999f6ac66531788cbac 100644 (file)
@@ -69,6 +69,7 @@ s32 arm_smccc_get_soc_id_revision(void)
 {
        return smccc_soc_id_revision;
 }
+EXPORT_SYMBOL_GPL(arm_smccc_get_soc_id_revision);
 
 static int __init smccc_devices_init(void)
 {
index 98b8fd16183e41068cc6108d19a6ef1704ade44e..80cac3a5f97678593ae790b761af661a3149d761 100644 (file)
@@ -78,6 +78,7 @@ static void cci_pci_free_irq(struct pci_dev *pcidev)
 #define PCIE_DEVICE_ID_SILICOM_PAC_N5011       0x1001
 #define PCIE_DEVICE_ID_INTEL_DFL               0xbcce
 /* PCI Subdevice ID for PCIE_DEVICE_ID_INTEL_DFL */
+#define PCIE_SUBDEVICE_ID_INTEL_D5005          0x138d
 #define PCIE_SUBDEVICE_ID_INTEL_N6000          0x1770
 #define PCIE_SUBDEVICE_ID_INTEL_N6001          0x1771
 #define PCIE_SUBDEVICE_ID_INTEL_C6100          0x17d4
@@ -101,6 +102,8 @@ static struct pci_device_id cci_pcie_id_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_D5005_VF),},
        {PCI_DEVICE(PCI_VENDOR_ID_SILICOM_DENMARK, PCIE_DEVICE_ID_SILICOM_PAC_N5010),},
        {PCI_DEVICE(PCI_VENDOR_ID_SILICOM_DENMARK, PCIE_DEVICE_ID_SILICOM_PAC_N5011),},
+       {PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_DFL,
+                       PCI_VENDOR_ID_INTEL, PCIE_SUBDEVICE_ID_INTEL_D5005),},
        {PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_DFL,
                        PCI_VENDOR_ID_INTEL, PCIE_SUBDEVICE_ID_INTEL_N6000),},
        {PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_DFL_VF,
index 1ee62cd58582b6496f0536fa7c45e2dc0305797f..25db014494a4de9bb8c44d0b2bd39d8786c3bb59 100644 (file)
@@ -92,7 +92,7 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type)
                case 0x5e:
                        return GPIOPANELCTL;
                default:
-                       return -EOPNOTSUPP;
+                       return -ENOTSUPP;
                }
        }
 
index 5ef8af8249806aa6c1b226ed4ab9219cca91d936..c097e310c9e841044a3ef214444170721d116537 100644 (file)
@@ -529,6 +529,7 @@ static const struct of_device_id lpc32xx_gpio_of_match[] = {
        { .compatible = "nxp,lpc3220-gpio", },
        { },
 };
+MODULE_DEVICE_TABLE(of, lpc32xx_gpio_of_match);
 
 static struct platform_driver lpc32xx_gpio_driver = {
        .driver         = {
index b75e0b12087ac78f9b50bc9ef77d4f06813ca72a..4b29abafecf6a466e5a81f6c8eeea70395e84823 100644 (file)
@@ -195,7 +195,8 @@ static int tng_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
 
 static void tng_irq_ack(struct irq_data *d)
 {
-       struct tng_gpio *priv = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct tng_gpio *priv = gpiochip_get_data(gc);
        irq_hw_number_t gpio = irqd_to_hwirq(d);
        void __iomem *gisr;
        u8 shift;
@@ -227,7 +228,8 @@ static void tng_irq_unmask_mask(struct tng_gpio *priv, u32 gpio, bool unmask)
 
 static void tng_irq_mask(struct irq_data *d)
 {
-       struct tng_gpio *priv = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct tng_gpio *priv = gpiochip_get_data(gc);
        irq_hw_number_t gpio = irqd_to_hwirq(d);
 
        tng_irq_unmask_mask(priv, gpio, false);
@@ -236,7 +238,8 @@ static void tng_irq_mask(struct irq_data *d)
 
 static void tng_irq_unmask(struct irq_data *d)
 {
-       struct tng_gpio *priv = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct tng_gpio *priv = gpiochip_get_data(gc);
        irq_hw_number_t gpio = irqd_to_hwirq(d);
 
        gpiochip_enable_irq(&priv->chip, gpio);
index d87dd06db40d07a5dd6fc1c0fa83be06d8e291f5..9130c691a2dd324f3e9ef3c57ff7c4f31fccee6f 100644 (file)
 #define  TEGRA186_GPIO_SCR_SEC_REN             BIT(27)
 #define  TEGRA186_GPIO_SCR_SEC_G1W             BIT(9)
 #define  TEGRA186_GPIO_SCR_SEC_G1R             BIT(1)
-#define  TEGRA186_GPIO_FULL_ACCESS             (TEGRA186_GPIO_SCR_SEC_WEN | \
-                                                TEGRA186_GPIO_SCR_SEC_REN | \
-                                                TEGRA186_GPIO_SCR_SEC_G1R | \
-                                                TEGRA186_GPIO_SCR_SEC_G1W)
-#define  TEGRA186_GPIO_SCR_SEC_ENABLE          (TEGRA186_GPIO_SCR_SEC_WEN | \
-                                                TEGRA186_GPIO_SCR_SEC_REN)
 
 /* control registers */
 #define TEGRA186_GPIO_ENABLE_CONFIG 0x00
@@ -177,10 +171,18 @@ static inline bool tegra186_gpio_is_accessible(struct tegra_gpio *gpio, unsigned
 
        value = __raw_readl(secure + TEGRA186_GPIO_SCR);
 
-       if ((value & TEGRA186_GPIO_SCR_SEC_ENABLE) == 0)
-               return true;
+       /*
+        * When SCR_SEC_[R|W]EN is unset, then we have full read/write access to all the
+        * registers for given GPIO pin.
+        * When SCR_SEC[R|W]EN is set, then there is need to further check the accompanying
+        * SCR_SEC_G1[R|W] bit to determine read/write access to all the registers for given
+        * GPIO pin.
+        */
 
-       if ((value & TEGRA186_GPIO_FULL_ACCESS) == TEGRA186_GPIO_FULL_ACCESS)
+       if (((value & TEGRA186_GPIO_SCR_SEC_REN) == 0 ||
+            ((value & TEGRA186_GPIO_SCR_SEC_REN) && (value & TEGRA186_GPIO_SCR_SEC_G1R))) &&
+            ((value & TEGRA186_GPIO_SCR_SEC_WEN) == 0 ||
+            ((value & TEGRA186_GPIO_SCR_SEC_WEN) && (value & TEGRA186_GPIO_SCR_SEC_G1W))))
                return true;
 
        return false;
index c18b6b47384f1b8b9a3a26c3ac7c5f125e82d365..94ca9d03c0949453abf3ad82e013698a7a97ffda 100644 (file)
@@ -104,7 +104,7 @@ static inline int to_reg(int gpio, enum ctrl_register type)
        unsigned int reg = type == CTRL_IN ? GPIO_IN_CTRL_BASE : GPIO_OUT_CTRL_BASE;
 
        if (gpio >= WCOVE_GPIO_NUM)
-               return -EOPNOTSUPP;
+               return -ENOTSUPP;
 
        return reg + gpio;
 }
index df58a6a1a67ec51f1bb81ff1bd8364be8a46cc13..e4d4e55c08ad5a3a11b7133e3f717110c958b09f 100644 (file)
@@ -220,7 +220,7 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
            (kfd_mem_limit.ttm_mem_used + ttm_mem_needed >
             kfd_mem_limit.max_ttm_mem_limit) ||
            (adev && xcp_id >= 0 && adev->kfd.vram_used[xcp_id] + vram_needed >
-            vram_size - reserved_for_pt)) {
+            vram_size - reserved_for_pt - atomic64_read(&adev->vram_pin_size))) {
                ret = -ENOMEM;
                goto release;
        }
@@ -1854,6 +1854,7 @@ err_node_allow:
 err_bo_create:
        amdgpu_amdkfd_unreserve_mem_limit(adev, aligned_size, flags, xcp_id);
 err_reserve_limit:
+       amdgpu_sync_free(&(*mem)->sync);
        mutex_destroy(&(*mem)->lock);
        if (gobj)
                drm_gem_object_put(gobj);
@@ -2900,13 +2901,12 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu *
 
        amdgpu_sync_create(&sync_obj);
 
-       /* Validate BOs and map them to GPUVM (update VM page tables). */
+       /* Validate BOs managed by KFD */
        list_for_each_entry(mem, &process_info->kfd_bo_list,
                            validate_list) {
 
                struct amdgpu_bo *bo = mem->bo;
                uint32_t domain = mem->domain;
-               struct kfd_mem_attachment *attachment;
                struct dma_resv_iter cursor;
                struct dma_fence *fence;
 
@@ -2931,6 +2931,25 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu *
                                goto validate_map_fail;
                        }
                }
+       }
+
+       if (failed_size)
+               pr_debug("0x%lx/0x%lx in system\n", failed_size, total_size);
+
+       /* Validate PDs, PTs and evicted DMABuf imports last. Otherwise BO
+        * validations above would invalidate DMABuf imports again.
+        */
+       ret = process_validate_vms(process_info, &exec.ticket);
+       if (ret) {
+               pr_debug("Validating VMs failed, ret: %d\n", ret);
+               goto validate_map_fail;
+       }
+
+       /* Update mappings managed by KFD. */
+       list_for_each_entry(mem, &process_info->kfd_bo_list,
+                           validate_list) {
+               struct kfd_mem_attachment *attachment;
+
                list_for_each_entry(attachment, &mem->attachments, list) {
                        if (!attachment->is_mapped)
                                continue;
@@ -2947,18 +2966,6 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu *
                }
        }
 
-       if (failed_size)
-               pr_debug("0x%lx/0x%lx in system\n", failed_size, total_size);
-
-       /* Validate PDs, PTs and evicted DMABuf imports last. Otherwise BO
-        * validations above would invalidate DMABuf imports again.
-        */
-       ret = process_validate_vms(process_info, &exec.ticket);
-       if (ret) {
-               pr_debug("Validating VMs failed, ret: %d\n", ret);
-               goto validate_map_fail;
-       }
-
        /* Update mappings not managed by KFD */
        list_for_each_entry(peer_vm, &process_info->vm_list_head,
                        vm_list_node) {
index 0a4b09709cfb149078c6284f2a0908cbde928430..ec888fc6ead8df0ce52ec00439e5f22ca7f4e9ff 100644 (file)
@@ -819,7 +819,7 @@ retry:
 
        p->bytes_moved += ctx.bytes_moved;
        if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
-           amdgpu_bo_in_cpu_visible_vram(bo))
+           amdgpu_res_cpu_visible(adev, bo->tbo.resource))
                p->bytes_moved_vis += ctx.bytes_moved;
 
        if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) {
index a00cf4756ad0e2f371742e760183882773a80243..1569bef030eac166ea6194427ca9c8489cc62796 100644 (file)
@@ -1132,6 +1132,7 @@ void amdgpu_mes_remove_ring(struct amdgpu_device *adev,
                return;
 
        amdgpu_mes_remove_hw_queue(adev, ring->hw_queue_id);
+       del_timer_sync(&ring->fence_drv.fallback_timer);
        amdgpu_ring_fini(ring);
        kfree(ring);
 }
index 010b0cb7693c9c3be5608f192cb19e583a285893..f6d503432a9ef966b2748acfd801ff04730cad6e 100644 (file)
@@ -605,6 +605,8 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
        else
                amdgpu_bo_placement_from_domain(bo, bp->domain);
        if (bp->type == ttm_bo_type_kernel)
+               bo->tbo.priority = 2;
+       else if (!(bp->flags & AMDGPU_GEM_CREATE_DISCARDABLE))
                bo->tbo.priority = 1;
 
        if (!bp->destroy)
@@ -617,8 +619,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
                return r;
 
        if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
-           bo->tbo.resource->mem_type == TTM_PL_VRAM &&
-           amdgpu_bo_in_cpu_visible_vram(bo))
+           amdgpu_res_cpu_visible(adev, bo->tbo.resource))
                amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved,
                                             ctx.bytes_moved);
        else
@@ -1242,14 +1243,18 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
  * amdgpu_bo_move_notify - notification about a memory move
  * @bo: pointer to a buffer object
  * @evict: if this move is evicting the buffer from the graphics address space
+ * @new_mem: new resource for backing the BO
  *
  * Marks the corresponding &amdgpu_bo buffer object as invalid, also performs
  * bookkeeping.
  * TTM driver callback which is called when ttm moves a buffer.
  */
-void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict)
+void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
+                          bool evict,
+                          struct ttm_resource *new_mem)
 {
        struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
+       struct ttm_resource *old_mem = bo->resource;
        struct amdgpu_bo *abo;
 
        if (!amdgpu_bo_is_amdgpu_bo(bo))
@@ -1261,34 +1266,36 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict)
        amdgpu_bo_kunmap(abo);
 
        if (abo->tbo.base.dma_buf && !abo->tbo.base.import_attach &&
-           bo->resource->mem_type != TTM_PL_SYSTEM)
+           old_mem && old_mem->mem_type != TTM_PL_SYSTEM)
                dma_buf_move_notify(abo->tbo.base.dma_buf);
 
-       /* remember the eviction */
-       if (evict)
-               atomic64_inc(&adev->num_evictions);
+       /* move_notify is called before move happens */
+       trace_amdgpu_bo_move(abo, new_mem ? new_mem->mem_type : -1,
+                            old_mem ? old_mem->mem_type : -1);
 }
 
 void amdgpu_bo_get_memory(struct amdgpu_bo *bo,
                          struct amdgpu_mem_stats *stats)
 {
+       struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+       struct ttm_resource *res = bo->tbo.resource;
        uint64_t size = amdgpu_bo_size(bo);
        struct drm_gem_object *obj;
        unsigned int domain;
        bool shared;
 
        /* Abort if the BO doesn't currently have a backing store */
-       if (!bo->tbo.resource)
+       if (!res)
                return;
 
        obj = &bo->tbo.base;
        shared = drm_gem_object_is_shared_for_memory_stats(obj);
 
-       domain = amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type);
+       domain = amdgpu_mem_type_to_domain(res->mem_type);
        switch (domain) {
        case AMDGPU_GEM_DOMAIN_VRAM:
                stats->vram += size;
-               if (amdgpu_bo_in_cpu_visible_vram(bo))
+               if (amdgpu_res_cpu_visible(adev, bo->tbo.resource))
                        stats->visible_vram += size;
                if (shared)
                        stats->vram_shared += size;
@@ -1389,10 +1396,7 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
        /* Remember that this BO was accessed by the CPU */
        abo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
 
-       if (bo->resource->mem_type != TTM_PL_VRAM)
-               return 0;
-
-       if (amdgpu_bo_in_cpu_visible_vram(abo))
+       if (amdgpu_res_cpu_visible(adev, bo->resource))
                return 0;
 
        /* Can't move a pinned BO to visible VRAM */
@@ -1415,7 +1419,7 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
 
        /* this should never happen */
        if (bo->resource->mem_type == TTM_PL_VRAM &&
-           !amdgpu_bo_in_cpu_visible_vram(abo))
+           !amdgpu_res_cpu_visible(adev, bo->resource))
                return VM_FAULT_SIGBUS;
 
        ttm_bo_move_to_lru_tail_unlocked(bo);
@@ -1579,6 +1583,7 @@ uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev,
  */
 u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m)
 {
+       struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
        struct dma_buf_attachment *attachment;
        struct dma_buf *dma_buf;
        const char *placement;
@@ -1587,10 +1592,11 @@ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m)
 
        if (dma_resv_trylock(bo->tbo.base.resv)) {
                unsigned int domain;
+
                domain = amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type);
                switch (domain) {
                case AMDGPU_GEM_DOMAIN_VRAM:
-                       if (amdgpu_bo_in_cpu_visible_vram(bo))
+                       if (amdgpu_res_cpu_visible(adev, bo->tbo.resource))
                                placement = "VRAM VISIBLE";
                        else
                                placement = "VRAM";
index be679c42b0b8cb5d127910803e79593910c72952..bc42ccbde659ac5ef1854b3a90d5561916faf422 100644 (file)
@@ -250,28 +250,6 @@ static inline u64 amdgpu_bo_mmap_offset(struct amdgpu_bo *bo)
        return drm_vma_node_offset_addr(&bo->tbo.base.vma_node);
 }
 
-/**
- * amdgpu_bo_in_cpu_visible_vram - check if BO is (partly) in visible VRAM
- */
-static inline bool amdgpu_bo_in_cpu_visible_vram(struct amdgpu_bo *bo)
-{
-       struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
-       struct amdgpu_res_cursor cursor;
-
-       if (!bo->tbo.resource || bo->tbo.resource->mem_type != TTM_PL_VRAM)
-               return false;
-
-       amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor);
-       while (cursor.remaining) {
-               if (cursor.start < adev->gmc.visible_vram_size)
-                       return true;
-
-               amdgpu_res_next(&cursor, cursor.size);
-       }
-
-       return false;
-}
-
 /**
  * amdgpu_bo_explicit_sync - return whether the bo is explicitly synced
  */
@@ -350,7 +328,9 @@ int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata,
 int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
                           size_t buffer_size, uint32_t *metadata_size,
                           uint64_t *flags);
-void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict);
+void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
+                          bool evict,
+                          struct ttm_resource *new_mem);
 void amdgpu_bo_release_notify(struct ttm_buffer_object *bo);
 vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
 void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
index fc418e670fdae27b699bdbefce8051ab128ab76c..109fe557a02bc85d562310bdc5fff082ecf8f2ba 100644 (file)
@@ -133,7 +133,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
 
                } else if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
                           !(abo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) &&
-                          amdgpu_bo_in_cpu_visible_vram(abo)) {
+                          amdgpu_res_cpu_visible(adev, bo->resource)) {
 
                        /* Try evicting to the CPU inaccessible part of VRAM
                         * first, but only set GTT as busy placement, so this
@@ -403,40 +403,55 @@ error:
        return r;
 }
 
-/*
- * amdgpu_mem_visible - Check that memory can be accessed by ttm_bo_move_memcpy
+/**
+ * amdgpu_res_cpu_visible - Check that resource can be accessed by CPU
+ * @adev: amdgpu device
+ * @res: the resource to check
  *
- * Called by amdgpu_bo_move()
+ * Returns: true if the full resource is CPU visible, false otherwise.
  */
-static bool amdgpu_mem_visible(struct amdgpu_device *adev,
-                              struct ttm_resource *mem)
+bool amdgpu_res_cpu_visible(struct amdgpu_device *adev,
+                           struct ttm_resource *res)
 {
-       u64 mem_size = (u64)mem->size;
        struct amdgpu_res_cursor cursor;
-       u64 end;
 
-       if (mem->mem_type == TTM_PL_SYSTEM ||
-           mem->mem_type == TTM_PL_TT)
+       if (!res)
+               return false;
+
+       if (res->mem_type == TTM_PL_SYSTEM || res->mem_type == TTM_PL_TT ||
+           res->mem_type == AMDGPU_PL_PREEMPT || res->mem_type == AMDGPU_PL_DOORBELL)
                return true;
-       if (mem->mem_type != TTM_PL_VRAM)
+
+       if (res->mem_type != TTM_PL_VRAM)
                return false;
 
-       amdgpu_res_first(mem, 0, mem_size, &cursor);
-       end = cursor.start + cursor.size;
+       amdgpu_res_first(res, 0, res->size, &cursor);
        while (cursor.remaining) {
+               if ((cursor.start + cursor.size) >= adev->gmc.visible_vram_size)
+                       return false;
                amdgpu_res_next(&cursor, cursor.size);
+       }
 
-               if (!cursor.remaining)
-                       break;
+       return true;
+}
 
-               /* ttm_resource_ioremap only supports contiguous memory */
-               if (end != cursor.start)
-                       return false;
+/*
+ * amdgpu_res_copyable - Check that memory can be accessed by ttm_bo_move_memcpy
+ *
+ * Called by amdgpu_bo_move()
+ */
+static bool amdgpu_res_copyable(struct amdgpu_device *adev,
+                               struct ttm_resource *mem)
+{
+       if (!amdgpu_res_cpu_visible(adev, mem))
+               return false;
 
-               end = cursor.start + cursor.size;
-       }
+       /* ttm_resource_ioremap only supports contiguous memory */
+       if (mem->mem_type == TTM_PL_VRAM &&
+           !(mem->placement & TTM_PL_FLAG_CONTIGUOUS))
+               return false;
 
-       return end <= adev->gmc.visible_vram_size;
+       return true;
 }
 
 /*
@@ -466,14 +481,16 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
 
        if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM &&
                         bo->ttm == NULL)) {
+               amdgpu_bo_move_notify(bo, evict, new_mem);
                ttm_bo_move_null(bo, new_mem);
-               goto out;
+               return 0;
        }
        if (old_mem->mem_type == TTM_PL_SYSTEM &&
            (new_mem->mem_type == TTM_PL_TT ||
             new_mem->mem_type == AMDGPU_PL_PREEMPT)) {
+               amdgpu_bo_move_notify(bo, evict, new_mem);
                ttm_bo_move_null(bo, new_mem);
-               goto out;
+               return 0;
        }
        if ((old_mem->mem_type == TTM_PL_TT ||
             old_mem->mem_type == AMDGPU_PL_PREEMPT) &&
@@ -483,9 +500,10 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
                        return r;
 
                amdgpu_ttm_backend_unbind(bo->bdev, bo->ttm);
+               amdgpu_bo_move_notify(bo, evict, new_mem);
                ttm_resource_free(bo, &bo->resource);
                ttm_bo_assign_mem(bo, new_mem);
-               goto out;
+               return 0;
        }
 
        if (old_mem->mem_type == AMDGPU_PL_GDS ||
@@ -497,8 +515,9 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
            new_mem->mem_type == AMDGPU_PL_OA ||
            new_mem->mem_type == AMDGPU_PL_DOORBELL) {
                /* Nothing to save here */
+               amdgpu_bo_move_notify(bo, evict, new_mem);
                ttm_bo_move_null(bo, new_mem);
-               goto out;
+               return 0;
        }
 
        if (bo->type == ttm_bo_type_device &&
@@ -510,27 +529,28 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
                abo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
        }
 
-       if (adev->mman.buffer_funcs_enabled) {
-               if (((old_mem->mem_type == TTM_PL_SYSTEM &&
-                     new_mem->mem_type == TTM_PL_VRAM) ||
-                    (old_mem->mem_type == TTM_PL_VRAM &&
-                     new_mem->mem_type == TTM_PL_SYSTEM))) {
-                       hop->fpfn = 0;
-                       hop->lpfn = 0;
-                       hop->mem_type = TTM_PL_TT;
-                       hop->flags = TTM_PL_FLAG_TEMPORARY;
-                       return -EMULTIHOP;
-               }
+       if (adev->mman.buffer_funcs_enabled &&
+           ((old_mem->mem_type == TTM_PL_SYSTEM &&
+             new_mem->mem_type == TTM_PL_VRAM) ||
+            (old_mem->mem_type == TTM_PL_VRAM &&
+             new_mem->mem_type == TTM_PL_SYSTEM))) {
+               hop->fpfn = 0;
+               hop->lpfn = 0;
+               hop->mem_type = TTM_PL_TT;
+               hop->flags = TTM_PL_FLAG_TEMPORARY;
+               return -EMULTIHOP;
+       }
 
+       amdgpu_bo_move_notify(bo, evict, new_mem);
+       if (adev->mman.buffer_funcs_enabled)
                r = amdgpu_move_blit(bo, evict, new_mem, old_mem);
-       } else {
+       else
                r = -ENODEV;
-       }
 
        if (r) {
                /* Check that all memory is CPU accessible */
-               if (!amdgpu_mem_visible(adev, old_mem) ||
-                   !amdgpu_mem_visible(adev, new_mem)) {
+               if (!amdgpu_res_copyable(adev, old_mem) ||
+                   !amdgpu_res_copyable(adev, new_mem)) {
                        pr_err("Move buffer fallback to memcpy unavailable\n");
                        return r;
                }
@@ -540,11 +560,10 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
                        return r;
        }
 
-       trace_amdgpu_bo_move(abo, new_mem->mem_type, old_mem->mem_type);
-out:
-       /* update statistics */
+       /* update statistics after the move */
+       if (evict)
+               atomic64_inc(&adev->num_evictions);
        atomic64_add(bo->base.size, &adev->num_bytes_moved);
-       amdgpu_bo_move_notify(bo, evict);
        return 0;
 }
 
@@ -557,7 +576,6 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_device *bdev,
                                     struct ttm_resource *mem)
 {
        struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
-       size_t bus_size = (size_t)mem->size;
 
        switch (mem->mem_type) {
        case TTM_PL_SYSTEM:
@@ -568,9 +586,6 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_device *bdev,
                break;
        case TTM_PL_VRAM:
                mem->bus.offset = mem->start << PAGE_SHIFT;
-               /* check if it's visible */
-               if ((mem->bus.offset + bus_size) > adev->gmc.visible_vram_size)
-                       return -EINVAL;
 
                if (adev->mman.aper_base_kaddr &&
                    mem->placement & TTM_PL_FLAG_CONTIGUOUS)
@@ -1548,7 +1563,7 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo,
 static void
 amdgpu_bo_delete_mem_notify(struct ttm_buffer_object *bo)
 {
-       amdgpu_bo_move_notify(bo, false);
+       amdgpu_bo_move_notify(bo, false, NULL);
 }
 
 static struct ttm_device_funcs amdgpu_bo_driver = {
index 65ec82141a8e012e8ba42b0bb627f1a4f504c465..32cf6b6f6efd96873c294648714f2c78f6ff9ec3 100644 (file)
@@ -139,6 +139,9 @@ int amdgpu_vram_mgr_reserve_range(struct amdgpu_vram_mgr *mgr,
 int amdgpu_vram_mgr_query_page_status(struct amdgpu_vram_mgr *mgr,
                                      uint64_t start);
 
+bool amdgpu_res_cpu_visible(struct amdgpu_device *adev,
+                           struct ttm_resource *res);
+
 int amdgpu_ttm_init(struct amdgpu_device *adev);
 void amdgpu_ttm_fini(struct amdgpu_device *adev);
 void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev,
index 0df97c3e3a700dccc7bc84d4688e1dc8e1b8a1e2..f7c73533e336fac3358c58e387cb27e102ac2684 100644 (file)
@@ -774,6 +774,9 @@ static int umsch_mm_late_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       if (amdgpu_in_reset(adev) || adev->in_s0ix || adev->in_suspend)
+               return 0;
+
        return umsch_mm_test(adev);
 }
 
index 4299ce386322e7cea27232ae05a1222f62f5a850..94089069c9ada61aa61b7c2b28601b764d47c172 100644 (file)
@@ -1613,6 +1613,37 @@ static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev,
        trace_amdgpu_vm_bo_map(bo_va, mapping);
 }
 
+/* Validate operation parameters to prevent potential abuse */
+static int amdgpu_vm_verify_parameters(struct amdgpu_device *adev,
+                                         struct amdgpu_bo *bo,
+                                         uint64_t saddr,
+                                         uint64_t offset,
+                                         uint64_t size)
+{
+       uint64_t tmp, lpfn;
+
+       if (saddr & AMDGPU_GPU_PAGE_MASK
+           || offset & AMDGPU_GPU_PAGE_MASK
+           || size & AMDGPU_GPU_PAGE_MASK)
+               return -EINVAL;
+
+       if (check_add_overflow(saddr, size, &tmp)
+           || check_add_overflow(offset, size, &tmp)
+           || size == 0 /* which also leads to end < begin */)
+               return -EINVAL;
+
+       /* make sure object fit at this offset */
+       if (bo && offset + size > amdgpu_bo_size(bo))
+               return -EINVAL;
+
+       /* Ensure last pfn not exceed max_pfn */
+       lpfn = (saddr + size - 1) >> AMDGPU_GPU_PAGE_SHIFT;
+       if (lpfn >= adev->vm_manager.max_pfn)
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
  * amdgpu_vm_bo_map - map bo inside a vm
  *
@@ -1639,21 +1670,14 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
        struct amdgpu_bo *bo = bo_va->base.bo;
        struct amdgpu_vm *vm = bo_va->base.vm;
        uint64_t eaddr;
+       int r;
 
-       /* validate the parameters */
-       if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK)
-               return -EINVAL;
-       if (saddr + size <= saddr || offset + size <= offset)
-               return -EINVAL;
-
-       /* make sure object fit at this offset */
-       eaddr = saddr + size - 1;
-       if ((bo && offset + size > amdgpu_bo_size(bo)) ||
-           (eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT))
-               return -EINVAL;
+       r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
+       if (r)
+               return r;
 
        saddr /= AMDGPU_GPU_PAGE_SIZE;
-       eaddr /= AMDGPU_GPU_PAGE_SIZE;
+       eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
 
        tmp = amdgpu_vm_it_iter_first(&vm->va, saddr, eaddr);
        if (tmp) {
@@ -1706,17 +1730,9 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
        uint64_t eaddr;
        int r;
 
-       /* validate the parameters */
-       if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK)
-               return -EINVAL;
-       if (saddr + size <= saddr || offset + size <= offset)
-               return -EINVAL;
-
-       /* make sure object fit at this offset */
-       eaddr = saddr + size - 1;
-       if ((bo && offset + size > amdgpu_bo_size(bo)) ||
-           (eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT))
-               return -EINVAL;
+       r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
+       if (r)
+               return r;
 
        /* Allocate all the needed memory */
        mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
@@ -1730,7 +1746,7 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
        }
 
        saddr /= AMDGPU_GPU_PAGE_SIZE;
-       eaddr /= AMDGPU_GPU_PAGE_SIZE;
+       eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
 
        mapping->start = saddr;
        mapping->last = eaddr;
@@ -1817,10 +1833,14 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev,
        struct amdgpu_bo_va_mapping *before, *after, *tmp, *next;
        LIST_HEAD(removed);
        uint64_t eaddr;
+       int r;
+
+       r = amdgpu_vm_verify_parameters(adev, NULL, saddr, 0, size);
+       if (r)
+               return r;
 
-       eaddr = saddr + size - 1;
        saddr /= AMDGPU_GPU_PAGE_SIZE;
-       eaddr /= AMDGPU_GPU_PAGE_SIZE;
+       eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
 
        /* Allocate all the needed memory */
        before = kzalloc(sizeof(*before), GFP_KERNEL);
index 6695481f870f8a0dc61edfbe0d9947b19288bc25..c23d97d34b7ec55e90f2f9f2f81f9a87e7c7ff26 100644 (file)
@@ -205,7 +205,7 @@ disable_dpm:
        dpm_ctl &= 0xfffffffe; /* Disable DPM */
        WREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_enable), dpm_ctl);
        dev_dbg(adev->dev, "%s: disable vpe dpm\n", __func__);
-       return 0;
+       return -EINVAL;
 }
 
 int amdgpu_vpe_psp_update_sram(struct amdgpu_device *adev)
index f90905ef32c76d62c3d490445b71388e9e0dc6bb..701146d649c353c9ace940af21a52c48fd37523c 100644 (file)
@@ -9186,7 +9186,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = {
                7 + /* PIPELINE_SYNC */
                SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
                SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
-               2 + /* VM_FLUSH */
+               4 + /* VM_FLUSH */
                8 + /* FENCE for VM_FLUSH */
                20 + /* GDS switch */
                4 + /* double SWITCH_BUFFER,
@@ -9276,7 +9276,6 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_kiq = {
                7 + /* gfx_v10_0_ring_emit_pipeline_sync */
                SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
                SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
-               2 + /* gfx_v10_0_ring_emit_vm_flush */
                8 + 8 + 8, /* gfx_v10_0_ring_emit_fence_kiq x3 for user fence, vm fence */
        .emit_ib_size = 7, /* gfx_v10_0_ring_emit_ib_compute */
        .emit_ib = gfx_v10_0_ring_emit_ib_compute,
index f7325b02a191f726196d4ad0ac6fa3d090ab9977..f00e05aba46a4e40b97ef0cbfe093a3b17ef350f 100644 (file)
@@ -6192,7 +6192,7 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = {
                7 + /* PIPELINE_SYNC */
                SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
                SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
-               2 + /* VM_FLUSH */
+               4 + /* VM_FLUSH */
                8 + /* FENCE for VM_FLUSH */
                20 + /* GDS switch */
                5 + /* COND_EXEC */
@@ -6278,7 +6278,6 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_kiq = {
                7 + /* gfx_v11_0_ring_emit_pipeline_sync */
                SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
                SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
-               2 + /* gfx_v11_0_ring_emit_vm_flush */
                8 + 8 + 8, /* gfx_v11_0_ring_emit_fence_kiq x3 for user fence, vm fence */
        .emit_ib_size = 7, /* gfx_v11_0_ring_emit_ib_compute */
        .emit_ib = gfx_v11_0_ring_emit_ib_compute,
index 6f97a6d0e6d0525cd6b7db25611d71506b3b0da6..99dbd2341120db5fa82b653daf76758052f7e306 100644 (file)
@@ -6981,7 +6981,6 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = {
                7 + /* gfx_v9_0_ring_emit_pipeline_sync */
                SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
                SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
-               2 + /* gfx_v9_0_ring_emit_vm_flush */
                8 + 8 + 8 + /* gfx_v9_0_ring_emit_fence x3 for user fence, vm fence */
                7 + /* gfx_v9_0_emit_mem_sync */
                5 + /* gfx_v9_0_emit_wave_limit for updating mmSPI_WCL_PIPE_PERCENT_GFX register */
@@ -7019,7 +7018,6 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_kiq = {
                7 + /* gfx_v9_0_ring_emit_pipeline_sync */
                SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
                SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
-               2 + /* gfx_v9_0_ring_emit_vm_flush */
                8 + 8 + 8, /* gfx_v9_0_ring_emit_fence_kiq x3 for user fence, vm fence */
        .emit_ib_size = 7, /* gfx_v9_0_ring_emit_ib_compute */
        .emit_fence = gfx_v9_0_ring_emit_fence_kiq,
index 82eab49be82bb99807e5caabf5079b32dfd4cb26..e708468ac54dd57fbe8fd46b250ff1bc6dd42bb2 100644 (file)
@@ -368,7 +368,8 @@ static void sdma_v4_4_2_ring_emit_hdp_flush(struct amdgpu_ring *ring)
        u32 ref_and_mask = 0;
        const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg;
 
-       ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me;
+       ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0
+                      << (ring->me % adev->sdma.num_inst_per_aid);
 
        sdma_v4_4_2_wait_reg_mem(ring, 0, 1,
                               adev->nbio.funcs->get_hdp_flush_done_offset(adev),
index 42f4bd250def622d490d355bac4883772def9c7a..da01b524b9f2a91dac57e75f7b1f1702116f6893 100644 (file)
@@ -280,17 +280,21 @@ static void sdma_v5_2_ring_emit_hdp_flush(struct amdgpu_ring *ring)
        u32 ref_and_mask = 0;
        const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg;
 
-       ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me;
-
-       amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
-                         SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(1) |
-                         SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* == */
-       amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_done_offset(adev)) << 2);
-       amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_req_offset(adev)) << 2);
-       amdgpu_ring_write(ring, ref_and_mask); /* reference */
-       amdgpu_ring_write(ring, ref_and_mask); /* mask */
-       amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) |
-                         SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */
+       if (ring->me > 1) {
+               amdgpu_asic_flush_hdp(adev, ring);
+       } else {
+               ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me;
+
+               amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
+                                 SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(1) |
+                                 SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* == */
+               amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_done_offset(adev)) << 2);
+               amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_req_offset(adev)) << 2);
+               amdgpu_ring_write(ring, ref_and_mask); /* reference */
+               amdgpu_ring_write(ring, ref_and_mask); /* mask */
+               amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) |
+                                 SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */
+       }
 }
 
 /**
index 769eb8f7bb3c570c90fb6325ecaeb0f49368ec24..09315dd5a1ec95a896ff62e3010746f1750757f8 100644 (file)
@@ -144,6 +144,12 @@ static int vpe_v6_1_load_microcode(struct amdgpu_vpe *vpe)
                        WREG32(vpe_get_reg_offset(vpe, j, regVPEC_CNTL), ret);
        }
 
+       /* setup collaborate mode */
+       vpe_v6_1_set_collaborate_mode(vpe, true);
+       /* setup DPM */
+       if (amdgpu_vpe_configure_dpm(vpe))
+               dev_warn(adev->dev, "VPE failed to enable DPM\n");
+
        /*
         * For VPE 6.1.1, still only need to add master's offset, and psp will apply it to slave as well.
         * Here use instance 0 as master.
@@ -159,11 +165,7 @@ static int vpe_v6_1_load_microcode(struct amdgpu_vpe *vpe)
                adev->vpe.cmdbuf_cpu_addr[0] = f32_offset;
                adev->vpe.cmdbuf_cpu_addr[1] = f32_cntl;
 
-               amdgpu_vpe_psp_update_sram(adev);
-               vpe_v6_1_set_collaborate_mode(vpe, true);
-               amdgpu_vpe_configure_dpm(vpe);
-
-               return 0;
+               return amdgpu_vpe_psp_update_sram(adev);
        }
 
        vpe_hdr = (const struct vpe_firmware_header_v1_0 *)adev->vpe.fw->data;
@@ -196,8 +198,6 @@ static int vpe_v6_1_load_microcode(struct amdgpu_vpe *vpe)
        }
 
        vpe_v6_1_halt(vpe, false);
-       vpe_v6_1_set_collaborate_mode(vpe, true);
-       amdgpu_vpe_configure_dpm(vpe);
 
        return 0;
 }
index bdc01ca9609a7e57fac05ee60d6866a5950e2b07..5c8d81bfce7ab14938c9a45cc23f3ab6beac1dd0 100644 (file)
@@ -509,10 +509,19 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
        start = start_mgr << PAGE_SHIFT;
        end = (last_mgr + 1) << PAGE_SHIFT;
 
+       r = amdgpu_amdkfd_reserve_mem_limit(node->adev,
+                                       prange->npages * PAGE_SIZE,
+                                       KFD_IOC_ALLOC_MEM_FLAGS_VRAM,
+                                       node->xcp ? node->xcp->id : 0);
+       if (r) {
+               dev_dbg(node->adev->dev, "failed to reserve VRAM, r: %ld\n", r);
+               return -ENOSPC;
+       }
+
        r = svm_range_vram_node_new(node, prange, true);
        if (r) {
                dev_dbg(node->adev->dev, "fail %ld to alloc vram\n", r);
-               return r;
+               goto out;
        }
        ttm_res_offset = (start_mgr - prange->start + prange->offset) << PAGE_SHIFT;
 
@@ -545,6 +554,11 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
                svm_range_vram_node_free(prange);
        }
 
+out:
+       amdgpu_amdkfd_unreserve_mem_limit(node->adev,
+                                       prange->npages * PAGE_SIZE,
+                                       KFD_IOC_ALLOC_MEM_FLAGS_VRAM,
+                                       node->xcp ? node->xcp->id : 0);
        return r < 0 ? r : 0;
 }
 
index 717a60d7a4ea953b8dfc369b09d855ad74b49659..451bb058cc62039eaf98c0e90487c0884042dfa4 100644 (file)
@@ -819,9 +819,9 @@ struct kfd_process *kfd_create_process(struct task_struct *thread)
        mutex_lock(&kfd_processes_mutex);
 
        if (kfd_is_locked()) {
-               mutex_unlock(&kfd_processes_mutex);
                pr_debug("KFD is locked! Cannot create process");
-               return ERR_PTR(-EINVAL);
+               process = ERR_PTR(-EINVAL);
+               goto out;
        }
 
        /* A prior open of /dev/kfd could have already created the process. */
@@ -829,6 +829,14 @@ struct kfd_process *kfd_create_process(struct task_struct *thread)
        if (process) {
                pr_debug("Process already found\n");
        } else {
+               /* If the process just called exec(3), it is possible that the
+                * cleanup of the kfd_process (following the release of the mm
+                * of the old process image) is still in the cleanup work queue.
+                * Make sure to drain any job before trying to recreate any
+                * resource for this process.
+                */
+               flush_workqueue(kfd_process_wq);
+
                process = create_process(thread);
                if (IS_ERR(process))
                        goto out;
@@ -1922,6 +1930,8 @@ static int signal_eviction_fence(struct kfd_process *p)
        rcu_read_lock();
        ef = dma_fence_get_rcu_safe(&p->ef);
        rcu_read_unlock();
+       if (!ef)
+               return -EINVAL;
 
        ret = dma_fence_signal(ef);
        dma_fence_put(ef);
@@ -1949,10 +1959,9 @@ static void evict_process_worker(struct work_struct *work)
                 * they are responsible stopping the queues and scheduling
                 * the restore work.
                 */
-               if (!signal_eviction_fence(p))
-                       queue_delayed_work(kfd_restore_wq, &p->restore_work,
-                               msecs_to_jiffies(PROCESS_RESTORE_TIME_MS));
-               else
+               if (signal_eviction_fence(p) ||
+                   mod_delayed_work(kfd_restore_wq, &p->restore_work,
+                                    msecs_to_jiffies(PROCESS_RESTORE_TIME_MS)))
                        kfd_process_restore_queues(p);
 
                pr_debug("Finished evicting pasid 0x%x\n", p->pasid);
@@ -2011,9 +2020,9 @@ static void restore_process_worker(struct work_struct *work)
        if (ret) {
                pr_debug("Failed to restore BOs of pasid 0x%x, retry after %d ms\n",
                         p->pasid, PROCESS_BACK_OFF_TIME_MS);
-               ret = queue_delayed_work(kfd_restore_wq, &p->restore_work,
-                               msecs_to_jiffies(PROCESS_BACK_OFF_TIME_MS));
-               WARN(!ret, "reschedule restore work failed\n");
+               if (mod_delayed_work(kfd_restore_wq, &p->restore_work,
+                                    msecs_to_jiffies(PROCESS_RESTORE_TIME_MS)))
+                       kfd_process_restore_queues(p);
        }
 }
 
index f0f7f48af4137acb088e2e903f803c345babc3ec..386875e6eb96bacb6585ae58c5620db1f41fde92 100644 (file)
@@ -3426,7 +3426,7 @@ svm_range_trigger_migration(struct mm_struct *mm, struct svm_range *prange,
                                mm, KFD_MIGRATE_TRIGGER_PREFETCH);
        *migrated = !r;
 
-       return r;
+       return 0;
 }
 
 int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence)
index 6d2f60c61decc36711953fa5b0dd67888c652a32..d6e71aa808d881f544053aa2b9c54e5d367cda79 100644 (file)
@@ -3029,6 +3029,7 @@ static int dm_resume(void *handle)
                        dc_stream_release(dm_new_crtc_state->stream);
                        dm_new_crtc_state->stream = NULL;
                }
+               dm_new_crtc_state->base.color_mgmt_changed = true;
        }
 
        for_each_new_plane_in_state(dm->cached_state, plane, new_plane_state, i) {
@@ -4536,15 +4537,18 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
        /* Determine whether to enable Replay support by default. */
        if (!(amdgpu_dc_debug_mask & DC_DISABLE_REPLAY)) {
                switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
-               case IP_VERSION(3, 1, 4):
-               case IP_VERSION(3, 1, 5):
-               case IP_VERSION(3, 1, 6):
-               case IP_VERSION(3, 2, 0):
-               case IP_VERSION(3, 2, 1):
-               case IP_VERSION(3, 5, 0):
-               case IP_VERSION(3, 5, 1):
-                       replay_feature_enabled = true;
-                       break;
+/*
+ * Disabled by default due to https://gitlab.freedesktop.org/drm/amd/-/issues/3344
+ *             case IP_VERSION(3, 1, 4):
+ *             case IP_VERSION(3, 1, 5):
+ *             case IP_VERSION(3, 1, 6):
+ *             case IP_VERSION(3, 2, 0):
+ *             case IP_VERSION(3, 2, 1):
+ *             case IP_VERSION(3, 5, 0):
+ *             case IP_VERSION(3, 5, 1):
+ *                     replay_feature_enabled = true;
+ *                     break;
+ */
                default:
                        replay_feature_enabled = amdgpu_dc_feature_mask & DC_REPLAY_MASK;
                        break;
index eee4945653e2d18d09f8bfc8175251499950f53c..c7715a17f388b34f3c2b9b0c3f2a26916f8bb509 100644 (file)
@@ -1495,7 +1495,9 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -1596,7 +1598,9 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -1681,7 +1685,9 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -1780,7 +1786,9 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -1865,7 +1873,9 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -1964,7 +1974,9 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -2045,7 +2057,9 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -2141,7 +2155,9 @@ static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *bu
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -2220,7 +2236,9 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -2276,7 +2294,9 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -2347,7 +2367,9 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -2418,7 +2440,9 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
index 05f392501c0ae3572250061b31defef7cde51fb5..ab31643b109698ec95a11da1aabdfa258705989a 100644 (file)
@@ -2948,6 +2948,7 @@ static enum bp_result construct_integrated_info(
                                result = get_integrated_info_v2_1(bp, info);
                                break;
                        case 2:
+                       case 3:
                                result = get_integrated_info_v2_2(bp, info);
                                break;
                        default:
index 644da463732093f9d3798b3de9565b5f7fd9ea0b..5506cf9b3672f80992c846b8686613427976bb81 100644 (file)
@@ -145,6 +145,10 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
         */
        clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
        if (safe_to_lower) {
+               if (clk_mgr_base->clks.dtbclk_en && !new_clocks->dtbclk_en) {
+                       dcn315_smu_set_dtbclk(clk_mgr, false);
+                       clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
+               }
                /* check that we're not already in lower */
                if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
                        display_count = dcn315_get_active_display_cnt_wa(dc, context);
@@ -160,6 +164,10 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
                        }
                }
        } else {
+               if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) {
+                       dcn315_smu_set_dtbclk(clk_mgr, true);
+                       clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
+               }
                /* check that we're not already in D0 */
                if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_MISSION_MODE) {
                        union display_idle_optimization_u idle_info = { 0 };
index bec252e1dd27a98263b5bd3299cc3dfd8ed089e9..e506e4f969ca9ffc90bdf8714c936a72aa9c2b17 100644 (file)
@@ -712,8 +712,12 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
                                         * since we calculate mode support based on softmax being the max UCLK
                                         * frequency.
                                         */
-                                       dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
-                                                       dc->clk_mgr->bw_params->dc_mode_softmax_memclk);
+                                       if (dc->debug.disable_dc_mode_overwrite) {
+                                               dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz);
+                                               dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz);
+                                       } else
+                                               dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+                                                               dc->clk_mgr->bw_params->dc_mode_softmax_memclk);
                                } else {
                                        dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz);
                                }
@@ -746,8 +750,13 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
                /* set UCLK to requested value if P-State switching is supported, or to re-enable P-State switching */
                if (clk_mgr_base->clks.p_state_change_support &&
                                (update_uclk || !clk_mgr_base->clks.prev_p_state_change_support) &&
-                               !dc->work_arounds.clock_update_disable_mask.uclk)
+                               !dc->work_arounds.clock_update_disable_mask.uclk) {
+                       if (dc->clk_mgr->dc_mode_softmax_enabled && dc->debug.disable_dc_mode_overwrite)
+                               dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK,
+                                               max((int)dc->clk_mgr->bw_params->dc_mode_softmax_memclk, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz)));
+
                        dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
+               }
 
                if (clk_mgr_base->clks.num_ways != new_clocks->num_ways &&
                                clk_mgr_base->clks.num_ways > new_clocks->num_ways) {
index 03b554e912a20d4ae58e5161d55943eb0bb7a0d9..d68c83e40d4d6c3bd89e66cc5ecc63ca14c010d0 100644 (file)
@@ -1801,6 +1801,9 @@ bool dc_validate_boot_timing(const struct dc *dc,
                return false;
        }
 
+       if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)
+               return false;
+
        if (dc->link_srv->edp_is_ilr_optimization_required(link, crtc_timing)) {
                DC_LOG_EVENT_LINK_TRAINING("Seamless boot disabled to optimize eDP link rate\n");
                return false;
index 5b7ad38f85e08f422c32e48bdb4b384b8bb75e08..65e45a0b4ff34351013a6e7f5debe0eb8c676e8d 100644 (file)
@@ -395,6 +395,12 @@ void dcn31_hpo_dp_link_enc_set_throttled_vcp_size(
                                x),
                        25));
 
+       // If y rounds up to integer, carry it over to x.
+       if (y >> 25) {
+               x += 1;
+               y = 0;
+       }
+
        switch (stream_encoder_inst) {
        case 0:
                REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL0, 0,
index e224a028d68accaf083a76a93eb7f0cdb940aedf..8a0460e86309775e83775093b04527f022e4a91c 100644 (file)
@@ -248,14 +248,12 @@ void dcn32_link_encoder_construct(
        enc10->base.hpd_source = init_data->hpd_source;
        enc10->base.connector = init_data->connector;
 
-       enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
-
-       enc10->base.features = *enc_features;
        if (enc10->base.connector.id == CONNECTOR_ID_USBC)
                enc10->base.features.flags.bits.DP_IS_USB_C = 1;
 
-       if (enc10->base.connector.id == CONNECTOR_ID_USBC)
-               enc10->base.features.flags.bits.DP_IS_USB_C = 1;
+       enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
+
+       enc10->base.features = *enc_features;
 
        enc10->base.transmitter = init_data->transmitter;
 
index 81e349d5835bbed499f03ef6eb33e5210c83d64b..da94e5309fbaf0f8e06a4a1aad4ce431a8d9f2cc 100644 (file)
@@ -184,6 +184,8 @@ void dcn35_link_encoder_construct(
        enc10->base.hpd_source = init_data->hpd_source;
        enc10->base.connector = init_data->connector;
 
+       if (enc10->base.connector.id == CONNECTOR_ID_USBC)
+               enc10->base.features.flags.bits.DP_IS_USB_C = 1;
 
        enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
 
@@ -238,8 +240,6 @@ void dcn35_link_encoder_construct(
        }
 
        enc10->base.features.flags.bits.HDMI_6GB_EN = 1;
-       if (enc10->base.connector.id == CONNECTOR_ID_USBC)
-               enc10->base.features.flags.bits.DP_IS_USB_C = 1;
 
        if (bp_funcs->get_connector_speed_cap_info)
                result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios,
index deb6d162a2d5c00df00b069a57e885b34a18e939..7307b7b8d8ad7595bcfbf09e0a39786df389398f 100644 (file)
@@ -291,6 +291,7 @@ static struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = {
        .do_urgent_latency_adjustment = false,
        .urgent_latency_adjustment_fabric_clock_component_us = 0,
        .urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
+       .dispclk_dppclk_vco_speed_mhz = 2400.0,
        .num_chans = 4,
        .dummy_pstate_latency_us = 10.0
 };
@@ -438,6 +439,7 @@ static struct _vcs_dpi_soc_bounding_box_st dcn3_16_soc = {
        .do_urgent_latency_adjustment = false,
        .urgent_latency_adjustment_fabric_clock_component_us = 0,
        .urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
+       .dispclk_dppclk_vco_speed_mhz = 2500.0,
 };
 
 void dcn31_zero_pipe_dcc_fraction(display_e2e_pipe_params_st *pipes,
index 5491b707cec881b9854ab96834503c1e88053380..5a965c26bf2095fa44c5f81e89c0feded2b99b38 100644 (file)
@@ -270,7 +270,7 @@ static void set_usb4_req_bw_req(struct dc_link *link, int req_bw)
 
        /* Error check whether requested and allocated are equal */
        req_bw = requested_bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
-       if (req_bw == link->dpia_bw_alloc_config.allocated_bw) {
+       if (req_bw && (req_bw == link->dpia_bw_alloc_config.allocated_bw)) {
                DC_LOG_ERROR("%s: Request bw equals to allocated bw for link(%d)\n",
                        __func__, link->link_index);
        }
@@ -341,6 +341,14 @@ bool link_dp_dpia_set_dptx_usb4_bw_alloc_support(struct dc_link *link)
                        ret = true;
                        init_usb4_bw_struct(link);
                        link->dpia_bw_alloc_config.bw_alloc_enabled = true;
+
+                       /*
+                        * During DP tunnel creation, CM preallocates BW and reduces estimated BW of other
+                        * DPIA. CM release preallocation only when allocation is complete. Do zero alloc
+                        * to make the CM to release preallocation and update estimated BW correctly for
+                        * all DPIAs per host router
+                        */
+                       link_dp_dpia_allocate_usb4_bandwidth_for_stream(link, 0);
                }
        }
 
index a2387cea1af9a184124121b3d631740e01c41484..622214b365a25aa50fc21a6dde5b7e6f192a55b7 100644 (file)
@@ -2449,6 +2449,7 @@ static bool dcn20_resource_construct(
        dc->caps.post_blend_color_processing = true;
        dc->caps.force_dp_tps4_for_cp2520 = true;
        dc->caps.extended_aux_timeout_support = true;
+       dc->caps.dmcub_support = true;
 
        /* Color pipeline capabilities */
        dc->caps.color.dpp.dcn_arch = 1;
index f09b9d49297e815f469cc54be1c1130711576a12..bbd0169010c2d50a2454e64f53342a9304ac6e89 100644 (file)
@@ -4261,6 +4261,13 @@ static int amdgpu_od_set_init(struct amdgpu_device *adev)
                }
        }
 
+       /*
+        * If gpu_od is the only member in the list, that means gpu_od is an
+        * empty directory, so remove it.
+        */
+       if (list_is_singular(&adev->pm.od_kobj_list))
+               goto err_out;
+
        return 0;
 
 err_out:
index 3957af057d54ff1ed8d5f5f9545e51562cb3973c..c977ebe88001df958c74dab7cd771c39807f6c62 100644 (file)
@@ -2294,6 +2294,17 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
        return sizeof(*gpu_metrics);
 }
 
+static void smu_v13_0_6_restore_pci_config(struct smu_context *smu)
+{
+       struct amdgpu_device *adev = smu->adev;
+       int i;
+
+       for (i = 0; i < 16; i++)
+               pci_write_config_dword(adev->pdev, i * 4,
+                                      adev->pdev->saved_config_space[i]);
+       pci_restore_msi_state(adev->pdev);
+}
+
 static int smu_v13_0_6_mode2_reset(struct smu_context *smu)
 {
        int ret = 0, index;
@@ -2315,6 +2326,20 @@ static int smu_v13_0_6_mode2_reset(struct smu_context *smu)
        /* Restore the config space saved during init */
        amdgpu_device_load_pci_state(adev->pdev);
 
+       /* Certain platforms have switches which assign virtual BAR values to
+        * devices. OS uses the virtual BAR values and device behind the switch
+        * is assgined another BAR value. When device's config space registers
+        * are queried, switch returns the virtual BAR values. When mode-2 reset
+        * is performed, switch is unaware of it, and will continue to return
+        * the same virtual values to the OS.This affects
+        * pci_restore_config_space() API as it doesn't write the value saved if
+        * the current value read from config space is the same as what is
+        * saved. As a workaround, make sure the config space is restored
+        * always.
+        */
+       if (!(adev->flags & AMD_IS_APU))
+               smu_v13_0_6_restore_pci_config(smu);
+
        dev_dbg(smu->adev->dev, "wait for reset ack\n");
        do {
                ret = smu_cmn_wait_for_response(smu);
index e440f458b6633d71ab5c49c5e07c3687b6b025e8..93337543aac32b50121f1698c3c79950e3e67f4f 100644 (file)
@@ -224,8 +224,8 @@ __drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane,
 
        __drm_atomic_helper_plane_duplicate_state(plane, &new_shadow_plane_state->base);
 
-       drm_format_conv_state_copy(&shadow_plane_state->fmtcnv_state,
-                                  &new_shadow_plane_state->fmtcnv_state);
+       drm_format_conv_state_copy(&new_shadow_plane_state->fmtcnv_state,
+                                  &shadow_plane_state->fmtcnv_state);
 }
 EXPORT_SYMBOL(__drm_gem_duplicate_shadow_plane_state);
 
index 734412aae94dde5c08e6e575c405fd9805e98d8d..a9bf426f69b365caa5b335e167109b7c7f5be90e 100644 (file)
@@ -164,26 +164,6 @@ int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value)
                *value = gpu->identity.eco_id;
                break;
 
-       case ETNAVIV_PARAM_GPU_NN_CORE_COUNT:
-               *value = gpu->identity.nn_core_count;
-               break;
-
-       case ETNAVIV_PARAM_GPU_NN_MAD_PER_CORE:
-               *value = gpu->identity.nn_mad_per_core;
-               break;
-
-       case ETNAVIV_PARAM_GPU_TP_CORE_COUNT:
-               *value = gpu->identity.tp_core_count;
-               break;
-
-       case ETNAVIV_PARAM_GPU_ON_CHIP_SRAM_SIZE:
-               *value = gpu->identity.on_chip_sram_size;
-               break;
-
-       case ETNAVIV_PARAM_GPU_AXI_SRAM_SIZE:
-               *value = gpu->identity.axi_sram_size;
-               break;
-
        default:
                DBG("%s: invalid param: %u", dev_name(gpu->dev), param);
                return -EINVAL;
@@ -663,8 +643,8 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu)
        /* Disable TX clock gating on affected core revisions. */
        if (etnaviv_is_model_rev(gpu, GC4000, 0x5222) ||
            etnaviv_is_model_rev(gpu, GC2000, 0x5108) ||
-           etnaviv_is_model_rev(gpu, GC2000, 0x6202) ||
-           etnaviv_is_model_rev(gpu, GC2000, 0x6203))
+           etnaviv_is_model_rev(gpu, GC7000, 0x6202) ||
+           etnaviv_is_model_rev(gpu, GC7000, 0x6203))
                pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX;
 
        /* Disable SE and RA clock gating on affected core revisions. */
index 7d5e9158e13c1aca6df49f254b00dd72d3a27a9e..197e0037732ec84998aba60b1769a2fc305ea1bf 100644 (file)
@@ -54,18 +54,6 @@ struct etnaviv_chip_identity {
        /* Number of Neural Network cores. */
        u32 nn_core_count;
 
-       /* Number of MAD units per Neural Network core. */
-       u32 nn_mad_per_core;
-
-       /* Number of Tensor Processing cores. */
-       u32 tp_core_count;
-
-       /* Size in bytes of the SRAM inside the NPU. */
-       u32 on_chip_sram_size;
-
-       /* Size in bytes of the SRAM across the AXI bus. */
-       u32 axi_sram_size;
-
        /* Size of the vertex cache. */
        u32 vertex_cache_size;
 
index d8e7334de8ceac8d608ad97c04c8c3184db9267b..8665f2658d51b302f7e2e8ad9f52a438ccbc5d6f 100644 (file)
@@ -17,10 +17,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .thread_count = 128,
                .shader_core_count = 1,
                .nn_core_count = 0,
-               .nn_mad_per_core = 0,
-               .tp_core_count = 0,
-               .on_chip_sram_size = 0,
-               .axi_sram_size = 0,
                .vertex_cache_size = 8,
                .vertex_output_buffer_size = 1024,
                .pixel_pipes = 1,
@@ -52,11 +48,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .register_max = 64,
                .thread_count = 256,
                .shader_core_count = 1,
-               .nn_core_count = 0,
-               .nn_mad_per_core = 0,
-               .tp_core_count = 0,
-               .on_chip_sram_size = 0,
-               .axi_sram_size = 0,
                .vertex_cache_size = 8,
                .vertex_output_buffer_size = 512,
                .pixel_pipes = 1,
@@ -89,10 +80,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .thread_count = 512,
                .shader_core_count = 2,
                .nn_core_count = 0,
-               .nn_mad_per_core = 0,
-               .tp_core_count = 0,
-               .on_chip_sram_size = 0,
-               .axi_sram_size = 0,
                .vertex_cache_size = 16,
                .vertex_output_buffer_size = 1024,
                .pixel_pipes = 1,
@@ -125,10 +112,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .thread_count = 512,
                .shader_core_count = 2,
                .nn_core_count = 0,
-               .nn_mad_per_core = 0,
-               .tp_core_count = 0,
-               .on_chip_sram_size = 0,
-               .axi_sram_size = 0,
                .vertex_cache_size = 16,
                .vertex_output_buffer_size = 1024,
                .pixel_pipes = 1,
@@ -160,11 +143,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .register_max = 64,
                .thread_count = 512,
                .shader_core_count = 2,
-               .nn_core_count = 0,
-               .nn_mad_per_core = 0,
-               .tp_core_count = 0,
-               .on_chip_sram_size = 0,
-               .axi_sram_size = 0,
                .vertex_cache_size = 16,
                .vertex_output_buffer_size = 1024,
                .pixel_pipes = 1,
@@ -197,10 +175,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .thread_count = 1024,
                .shader_core_count = 4,
                .nn_core_count = 0,
-               .nn_mad_per_core = 0,
-               .tp_core_count = 0,
-               .on_chip_sram_size = 0,
-               .axi_sram_size = 0,
                .vertex_cache_size = 16,
                .vertex_output_buffer_size = 1024,
                .pixel_pipes = 2,
@@ -233,10 +207,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .thread_count = 256,
                .shader_core_count = 1,
                .nn_core_count = 8,
-               .nn_mad_per_core = 64,
-               .tp_core_count = 4,
-               .on_chip_sram_size = 524288,
-               .axi_sram_size = 1048576,
                .vertex_cache_size = 16,
                .vertex_output_buffer_size = 1024,
                .pixel_pipes = 1,
@@ -269,10 +239,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .thread_count = 256,
                .shader_core_count = 1,
                .nn_core_count = 6,
-               .nn_mad_per_core = 64,
-               .tp_core_count = 3,
-               .on_chip_sram_size = 262144,
-               .axi_sram_size = 0,
                .vertex_cache_size = 16,
                .vertex_output_buffer_size = 1024,
                .pixel_pipes = 1,
index 4f302cd5e1a6ca3a6fb1f15241c9568fc5ea74e7..58fed80c7392a02c317011365c9ce3165412bf3d 100644 (file)
@@ -34,7 +34,6 @@ gma500_gfx-y += \
          psb_intel_lvds.o \
          psb_intel_modes.o \
          psb_intel_sdvo.o \
-         psb_lid.o \
          psb_irq.o
 
 gma500_gfx-$(CONFIG_ACPI) +=  opregion.o
index dcfcd7b89d4a1dfe9fb5092b7aa63a111785b7fc..6dece8f0e380f7a447d582d6f914caa8d3d3704a 100644 (file)
@@ -73,8 +73,7 @@ static int psb_backlight_setup(struct drm_device *dev)
        }
 
        psb_intel_lvds_set_brightness(dev, PSB_MAX_BRIGHTNESS);
-       /* This must occur after the backlight is properly initialised */
-       psb_lid_timer_init(dev_priv);
+
        return 0;
 }
 
@@ -259,8 +258,6 @@ static int psb_chip_setup(struct drm_device *dev)
 
 static void psb_chip_teardown(struct drm_device *dev)
 {
-       struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
-       psb_lid_timer_takedown(dev_priv);
        gma_intel_teardown_gmbus(dev);
 }
 
index c5edfa4aa4ccdd526fa39a53e30f24a0fee41d28..83c17689c454f7c27955ad37dcf7ae2a6399c95c 100644 (file)
 #define PSB_NUM_VBLANKS 2
 
 #define PSB_WATCHDOG_DELAY (HZ * 2)
-#define PSB_LID_DELAY (HZ / 10)
 
 #define PSB_MAX_BRIGHTNESS             100
 
@@ -491,11 +490,7 @@ struct drm_psb_private {
        /* Hotplug handling */
        struct work_struct hotplug_work;
 
-       /* LID-Switch */
-       spinlock_t lid_lock;
-       struct timer_list lid_timer;
        struct psb_intel_opregion opregion;
-       u32 lid_last_state;
 
        /* Watchdog */
        uint32_t apm_reg;
@@ -591,10 +586,6 @@ struct psb_ops {
        int i2c_bus;            /* I2C bus identifier for Moorestown */
 };
 
-/* psb_lid.c */
-extern void psb_lid_timer_init(struct drm_psb_private *dev_priv);
-extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv);
-
 /* modesetting */
 extern void psb_modeset_init(struct drm_device *dev);
 extern void psb_modeset_cleanup(struct drm_device *dev);
diff --git a/drivers/gpu/drm/gma500/psb_lid.c b/drivers/gpu/drm/gma500/psb_lid.c
deleted file mode 100644 (file)
index 58a7fe3..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
- *
- * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
- **************************************************************************/
-
-#include <linux/spinlock.h>
-
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_reg.h"
-
-static void psb_lid_timer_func(struct timer_list *t)
-{
-       struct drm_psb_private *dev_priv = from_timer(dev_priv, t, lid_timer);
-       struct drm_device *dev = (struct drm_device *)&dev_priv->dev;
-       struct timer_list *lid_timer = &dev_priv->lid_timer;
-       unsigned long irq_flags;
-       u32 __iomem *lid_state = dev_priv->opregion.lid_state;
-       u32 pp_status;
-
-       if (readl(lid_state) == dev_priv->lid_last_state)
-               goto lid_timer_schedule;
-
-       if ((readl(lid_state)) & 0x01) {
-               /*lid state is open*/
-               REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON);
-               do {
-                       pp_status = REG_READ(PP_STATUS);
-               } while ((pp_status & PP_ON) == 0 &&
-                        (pp_status & PP_SEQUENCE_MASK) != 0);
-
-               if (REG_READ(PP_STATUS) & PP_ON) {
-                       /*FIXME: should be backlight level before*/
-                       psb_intel_lvds_set_brightness(dev, 100);
-               } else {
-                       DRM_DEBUG("LVDS panel never powered up");
-                       return;
-               }
-       } else {
-               psb_intel_lvds_set_brightness(dev, 0);
-
-               REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON);
-               do {
-                       pp_status = REG_READ(PP_STATUS);
-               } while ((pp_status & PP_ON) == 0);
-       }
-       dev_priv->lid_last_state =  readl(lid_state);
-
-lid_timer_schedule:
-       spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
-       if (!timer_pending(lid_timer)) {
-               lid_timer->expires = jiffies + PSB_LID_DELAY;
-               add_timer(lid_timer);
-       }
-       spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
-}
-
-void psb_lid_timer_init(struct drm_psb_private *dev_priv)
-{
-       struct timer_list *lid_timer = &dev_priv->lid_timer;
-       unsigned long irq_flags;
-
-       spin_lock_init(&dev_priv->lid_lock);
-       spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
-
-       timer_setup(lid_timer, psb_lid_timer_func, 0);
-
-       lid_timer->expires = jiffies + PSB_LID_DELAY;
-
-       add_timer(lid_timer);
-       spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
-}
-
-void psb_lid_timer_takedown(struct drm_psb_private *dev_priv)
-{
-       del_timer_sync(&dev_priv->lid_timer);
-}
-
index 408dbe63a90cfd5c5a5b51aa80fdd8bf7aaadde5..a0c5c41c8aa24a454c7c6ec10529ef8062ee3e9d 100644 (file)
@@ -7,13 +7,14 @@
 #include "pvr_rogue_mips.h"
 
 #include <asm/page.h>
+#include <linux/math.h>
 #include <linux/types.h>
 
 /* Forward declaration from pvr_gem.h. */
 struct pvr_gem_object;
 
-#define PVR_MIPS_PT_PAGE_COUNT ((ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * ROGUE_MIPSFW_PAGE_SIZE_4K) \
-                               >> PAGE_SHIFT)
+#define PVR_MIPS_PT_PAGE_COUNT DIV_ROUND_UP(ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * ROGUE_MIPSFW_PAGE_SIZE_4K, PAGE_SIZE)
+
 /**
  * struct pvr_fw_mips_data - MIPS-specific data
  */
index 6f5d376d8fcc1ecb6d9faa80b4b06ba4cd1b21e4..a11d16a16c3b25d288c07bba8ce4f545b3bda32d 100644 (file)
@@ -15,7 +15,9 @@ struct nvkm_gsp_mem {
 };
 
 struct nvkm_gsp_radix3 {
-       struct nvkm_gsp_mem mem[3];
+       struct nvkm_gsp_mem lvl0;
+       struct nvkm_gsp_mem lvl1;
+       struct sg_table lvl2;
 };
 
 int nvkm_gsp_sg(struct nvkm_device *, u64 size, struct sg_table *);
index 479effcf607e261fac73361958a0a855cf90d315..79cfab53f80e259093b7ae0f04310f6470a3c930 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "nouveau_drv.h"
+#include "nouveau_bios.h"
 #include "nouveau_reg.h"
 #include "dispnv04/hw.h"
 #include "nouveau_encoder.h"
@@ -1677,7 +1678,7 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
         */
        if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) {
                if (*conn == 0xf2005014 && *conf == 0xffffffff) {
-                       fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, 1);
+                       fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, DCB_OUTPUT_B);
                        return false;
                }
        }
@@ -1763,26 +1764,26 @@ fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios)
 #ifdef __powerpc__
        /* Apple iMac G4 NV17 */
        if (of_machine_is_compatible("PowerMac4,5")) {
-               fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, 1);
-               fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, 2);
+               fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, DCB_OUTPUT_B);
+               fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, DCB_OUTPUT_C);
                return;
        }
 #endif
 
        /* Make up some sane defaults */
        fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG,
-                            bios->legacy.i2c_indices.crt, 1, 1);
+                            bios->legacy.i2c_indices.crt, 1, DCB_OUTPUT_B);
 
        if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
                fabricate_dcb_output(dcb, DCB_OUTPUT_TV,
                                     bios->legacy.i2c_indices.tv,
-                                    all_heads, 0);
+                                    all_heads, DCB_OUTPUT_A);
 
        else if (bios->tmds.output0_script_ptr ||
                 bios->tmds.output1_script_ptr)
                fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS,
                                     bios->legacy.i2c_indices.panel,
-                                    all_heads, 1);
+                                    all_heads, DCB_OUTPUT_B);
 }
 
 static int
index 7de7707ec6a895ee2a914150008425a21041bf9c..a72c45809484ab58023dfa0dc5172f67adcfdc23 100644 (file)
@@ -225,12 +225,18 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
        u8 *dpcd = nv_encoder->dp.dpcd;
        int ret = NOUVEAU_DP_NONE, hpd;
 
-       /* If we've already read the DPCD on an eDP device, we don't need to
-        * reread it as it won't change
+       /* eDP ports don't support hotplugging - so there's no point in probing eDP ports unless we
+        * haven't probed them once before.
         */
-       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP &&
-           dpcd[DP_DPCD_REV] != 0)
-               return NOUVEAU_DP_SST;
+       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+               if (connector->status == connector_status_connected)
+                       return NOUVEAU_DP_SST;
+               else if (connector->status == connector_status_disconnected)
+                       return NOUVEAU_DP_NONE;
+       }
+
+       // Ensure that the aux bus is enabled for probing
+       drm_dp_dpcd_set_powered(&nv_connector->aux, true);
 
        mutex_lock(&nv_encoder->dp.hpd_irq_lock);
        if (mstm) {
@@ -293,6 +299,13 @@ out:
        if (mstm && !mstm->suspended && ret != NOUVEAU_DP_MST)
                nv50_mstm_remove(mstm);
 
+       /* GSP doesn't like when we try to do aux transactions on a port it considers disconnected,
+        * and since we don't really have a usecase for that anyway - just disable the aux bus here
+        * if we've decided the connector is disconnected
+        */
+       if (ret == NOUVEAU_DP_NONE)
+               drm_dp_dpcd_set_powered(&nv_connector->aux, false);
+
        mutex_unlock(&nv_encoder->dp.hpd_irq_lock);
        return ret;
 }
index adc60b25f8e6c61e51c7db37805fa24a89378fae..141b0a513bf52814e1977e916d81593b215de0d9 100644 (file)
@@ -205,7 +205,9 @@ nvkm_firmware_dtor(struct nvkm_firmware *fw)
                break;
        case NVKM_FIRMWARE_IMG_DMA:
                nvkm_memory_unref(&memory);
-               dma_free_coherent(fw->device->dev, sg_dma_len(&fw->mem.sgl), fw->img, fw->phys);
+               dma_unmap_single(fw->device->dev, fw->phys, sg_dma_len(&fw->mem.sgl),
+                                DMA_TO_DEVICE);
+               kfree(fw->img);
                break;
        case NVKM_FIRMWARE_IMG_SGT:
                nvkm_memory_unref(&memory);
@@ -235,14 +237,17 @@ nvkm_firmware_ctor(const struct nvkm_firmware_func *func, const char *name,
                fw->img = kmemdup(src, fw->len, GFP_KERNEL);
                break;
        case NVKM_FIRMWARE_IMG_DMA: {
-               dma_addr_t addr;
-
                len = ALIGN(fw->len, PAGE_SIZE);
 
-               fw->img = dma_alloc_coherent(fw->device->dev, len, &addr, GFP_KERNEL);
-               if (fw->img) {
-                       memcpy(fw->img, src, fw->len);
-                       fw->phys = addr;
+               fw->img = kmalloc(len, GFP_KERNEL);
+               if (!fw->img)
+                       return -ENOMEM;
+
+               memcpy(fw->img, src, fw->len);
+               fw->phys = dma_map_single(fw->device->dev, fw->img, len, DMA_TO_DEVICE);
+               if (dma_mapping_error(fw->device->dev, fw->phys)) {
+                       kfree(fw->img);
+                       return -EFAULT;
                }
 
                sg_init_one(&fw->mem.sgl, fw->img, len);
index 9858c1438aa7feda7d84ff5442f611b23f101b2d..abe41f7a34045531e90ca98b74ab03aedf5538c5 100644 (file)
@@ -1624,7 +1624,7 @@ r535_gsp_wpr_meta_init(struct nvkm_gsp *gsp)
        meta->magic = GSP_FW_WPR_META_MAGIC;
        meta->revision = GSP_FW_WPR_META_REVISION;
 
-       meta->sysmemAddrOfRadix3Elf = gsp->radix3.mem[0].addr;
+       meta->sysmemAddrOfRadix3Elf = gsp->radix3.lvl0.addr;
        meta->sizeOfRadix3Elf = gsp->fb.wpr2.elf.size;
 
        meta->sysmemAddrOfBootloader = gsp->boot.fw.addr;
@@ -1919,8 +1919,9 @@ nvkm_gsp_sg(struct nvkm_device *device, u64 size, struct sg_table *sgt)
 static void
 nvkm_gsp_radix3_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_radix3 *rx3)
 {
-       for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--)
-               nvkm_gsp_mem_dtor(gsp, &rx3->mem[i]);
+       nvkm_gsp_sg_free(gsp->subdev.device, &rx3->lvl2);
+       nvkm_gsp_mem_dtor(gsp, &rx3->lvl1);
+       nvkm_gsp_mem_dtor(gsp, &rx3->lvl0);
 }
 
 /**
@@ -1960,36 +1961,60 @@ static int
 nvkm_gsp_radix3_sg(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size,
                   struct nvkm_gsp_radix3 *rx3)
 {
-       u64 addr;
+       struct sg_dma_page_iter sg_dma_iter;
+       struct scatterlist *sg;
+       size_t bufsize;
+       u64 *pte;
+       int ret, i, page_idx = 0;
 
-       for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--) {
-               u64 *ptes;
-               size_t bufsize;
-               int ret, idx;
+       ret = nvkm_gsp_mem_ctor(gsp, GSP_PAGE_SIZE, &rx3->lvl0);
+       if (ret)
+               return ret;
 
-               bufsize = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), GSP_PAGE_SIZE);
-               ret = nvkm_gsp_mem_ctor(gsp, bufsize, &rx3->mem[i]);
-               if (ret)
-                       return ret;
+       ret = nvkm_gsp_mem_ctor(gsp, GSP_PAGE_SIZE, &rx3->lvl1);
+       if (ret)
+               goto lvl1_fail;
 
-               ptes = rx3->mem[i].data;
-               if (i == 2) {
-                       struct scatterlist *sgl;
+       // Allocate level 2
+       bufsize = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), GSP_PAGE_SIZE);
+       ret = nvkm_gsp_sg(gsp->subdev.device, bufsize, &rx3->lvl2);
+       if (ret)
+               goto lvl2_fail;
 
-                       for_each_sgtable_dma_sg(sgt, sgl, idx) {
-                               for (int j = 0; j < sg_dma_len(sgl) / GSP_PAGE_SIZE; j++)
-                                       *ptes++ = sg_dma_address(sgl) + (GSP_PAGE_SIZE * j);
-                       }
-               } else {
-                       for (int j = 0; j < size / GSP_PAGE_SIZE; j++)
-                               *ptes++ = addr + GSP_PAGE_SIZE * j;
+       // Write the bus address of level 1 to level 0
+       pte = rx3->lvl0.data;
+       *pte = rx3->lvl1.addr;
+
+       // Write the bus address of each page in level 2 to level 1
+       pte = rx3->lvl1.data;
+       for_each_sgtable_dma_page(&rx3->lvl2, &sg_dma_iter, 0)
+               *pte++ = sg_page_iter_dma_address(&sg_dma_iter);
+
+       // Finally, write the bus address of each page in sgt to level 2
+       for_each_sgtable_sg(&rx3->lvl2, sg, i) {
+               void *sgl_end;
+
+               pte = sg_virt(sg);
+               sgl_end = (void *)pte + sg->length;
+
+               for_each_sgtable_dma_page(sgt, &sg_dma_iter, page_idx) {
+                       *pte++ = sg_page_iter_dma_address(&sg_dma_iter);
+                       page_idx++;
+
+                       // Go to the next scatterlist for level 2 if we've reached the end
+                       if ((void *)pte >= sgl_end)
+                               break;
                }
+       }
 
-               size = rx3->mem[i].size;
-               addr = rx3->mem[i].addr;
+       if (ret) {
+lvl2_fail:
+               nvkm_gsp_mem_dtor(gsp, &rx3->lvl1);
+lvl1_fail:
+               nvkm_gsp_mem_dtor(gsp, &rx3->lvl0);
        }
 
-       return 0;
+       return ret;
 }
 
 int
@@ -2021,7 +2046,7 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
                sr = gsp->sr.meta.data;
                sr->magic = GSP_FW_SR_META_MAGIC;
                sr->revision = GSP_FW_SR_META_REVISION;
-               sr->sysmemAddrOfSuspendResumeData = gsp->sr.radix3.mem[0].addr;
+               sr->sysmemAddrOfSuspendResumeData = gsp->sr.radix3.lvl0.addr;
                sr->sizeOfSuspendResumeData = len;
 
                mbox0 = lower_32_bits(gsp->sr.meta.addr);
index a7f3fc342d87e03b031b5008d939c2eb46f49404..dd5b5a17ece0beed225888888d6c01a0afcf67c9 100644 (file)
@@ -222,8 +222,11 @@ nv50_instobj_acquire(struct nvkm_memory *memory)
        void __iomem *map = NULL;
 
        /* Already mapped? */
-       if (refcount_inc_not_zero(&iobj->maps))
+       if (refcount_inc_not_zero(&iobj->maps)) {
+               /* read barrier match the wmb on refcount set */
+               smp_rmb();
                return iobj->map;
+       }
 
        /* Take the lock, and re-check that another thread hasn't
         * already mapped the object in the meantime.
@@ -250,6 +253,8 @@ nv50_instobj_acquire(struct nvkm_memory *memory)
                        iobj->base.memory.ptrs = &nv50_instobj_fast;
                else
                        iobj->base.memory.ptrs = &nv50_instobj_slow;
+               /* barrier to ensure the ptrs are written before refcount is set */
+               smp_wmb();
                refcount_set(&iobj->maps, 1);
        }
 
index d037b3b8b9993458a8f1615902363a6663a94052..5b15d0294836756a1e3cfced716b86cd4e093e76 100644 (file)
@@ -177,7 +177,7 @@ config DRM_PANEL_ILITEK_IL9322
 
 config DRM_PANEL_ILITEK_ILI9341
        tristate "Ilitek ILI9341 240x320 QVGA panels"
-       depends on OF && SPI
+       depends on SPI
        select DRM_KMS_HELPER
        select DRM_GEM_DMA_HELPER
        depends on BACKLIGHT_CLASS_DEVICE
index 3574681891e816f5f32a012814e22f7335f687d2..b933380b7eb783fad1d1101b61d7a630ade11315 100644 (file)
@@ -22,8 +22,9 @@
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/gpio/consumer.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
-#include <linux/of.h>
+#include <linux/property.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 
@@ -421,7 +422,7 @@ static int ili9341_dpi_prepare(struct drm_panel *panel)
 
        ili9341_dpi_init(ili);
 
-       return ret;
+       return 0;
 }
 
 static int ili9341_dpi_enable(struct drm_panel *panel)
@@ -691,7 +692,7 @@ static int ili9341_dpi_probe(struct spi_device *spi, struct gpio_desc *dc,
         * Every new incarnation of this display must have a unique
         * data entry for the system in this driver.
         */
-       ili->conf = of_device_get_match_data(dev);
+       ili->conf = device_get_match_data(dev);
        if (!ili->conf) {
                dev_err(dev, "missing device configuration\n");
                return -ENODEV;
@@ -714,18 +715,18 @@ static int ili9341_probe(struct spi_device *spi)
 
        reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
        if (IS_ERR(reset))
-               dev_err(dev, "Failed to get gpio 'reset'\n");
+               return dev_err_probe(dev, PTR_ERR(reset), "Failed to get gpio 'reset'\n");
 
        dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW);
        if (IS_ERR(dc))
-               dev_err(dev, "Failed to get gpio 'dc'\n");
+               return dev_err_probe(dev, PTR_ERR(dc), "Failed to get gpio 'dc'\n");
 
        if (!strcmp(id->name, "sf-tc240t-9370-t"))
                return ili9341_dpi_probe(spi, dc, reset);
        else if (!strcmp(id->name, "yx240qv29"))
                return ili9341_dbi_probe(spi, dc, reset);
 
-       return -1;
+       return -ENODEV;
 }
 
 static void ili9341_remove(struct spi_device *spi)
index cb7406d7446695ebd3566230f3e11fca3b4cc323..c39fe0fc5d69c646915561bc3d4cb5cfc5411ac1 100644 (file)
@@ -614,8 +614,6 @@ static void nt36672e_panel_remove(struct mipi_dsi_device *dsi)
        struct nt36672e_panel *ctx = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(ctx->dsi);
-       mipi_dsi_device_unregister(ctx->dsi);
-
        drm_panel_remove(&ctx->panel);
 }
 
index 775144695283f54dcb1c527e58c9604cfd6da207..b15ca56a09a74a06f8bfcd0b4053d554ced9b58d 100644 (file)
@@ -253,8 +253,6 @@ static void visionox_rm69299_remove(struct mipi_dsi_device *dsi)
        struct visionox_rm69299 *ctx = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(ctx->dsi);
-       mipi_dsi_device_unregister(ctx->dsi);
-
        drm_panel_remove(&ctx->panel);
 }
 
index 94947229888ba7888aa6992116af8ab985219dbe..b7f22597ee95e798bb104894052997e332c298c6 100644 (file)
@@ -424,7 +424,7 @@ typedef struct _ATOM_PPLIB_SUMO_CLOCK_INFO{
 typedef struct _ATOM_PPLIB_STATE_V2
 {
       //number of valid dpm levels in this state; Driver uses it to calculate the whole 
-      //size of the state: sizeof(ATOM_PPLIB_STATE_V2) + (ucNumDPMLevels - 1) * sizeof(UCHAR)
+      //size of the state: struct_size(ATOM_PPLIB_STATE_V2, clockInfoIndex, ucNumDPMLevels)
       UCHAR ucNumDPMLevels;
       
       //a index to the array of nonClockInfos
@@ -432,14 +432,14 @@ typedef struct _ATOM_PPLIB_STATE_V2
       /**
       * Driver will read the first ucNumDPMLevels in this array
       */
-      UCHAR clockInfoIndex[1];
+      UCHAR clockInfoIndex[] __counted_by(ucNumDPMLevels);
 } ATOM_PPLIB_STATE_V2;
 
 typedef struct _StateArray{
     //how many states we have 
     UCHAR ucNumEntries;
     
-    ATOM_PPLIB_STATE_V2 states[1];
+    ATOM_PPLIB_STATE_V2 states[] __counted_by(ucNumEntries);
 }StateArray;
 
 
@@ -450,7 +450,7 @@ typedef struct _ClockInfoArray{
     //sizeof(ATOM_PPLIB_CLOCK_INFO)
     UCHAR ucEntrySize;
     
-    UCHAR clockInfo[1];
+    UCHAR clockInfo[] __counted_by(ucNumEntries);
 }ClockInfoArray;
 
 typedef struct _NonClockInfoArray{
@@ -460,7 +460,7 @@ typedef struct _NonClockInfoArray{
     //sizeof(ATOM_PPLIB_NONCLOCK_INFO)
     UCHAR ucEntrySize;
     
-    ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[1];
+    ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[] __counted_by(ucNumEntries);
 }NonClockInfoArray;
 
 typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Record
index bb1f0a3371ab5de484a81ad040347c9a5a8d4e76..10793a433bf58697fcdfce8e850ebfdd55ec7284 100644 (file)
@@ -923,8 +923,12 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
                max_device = ATOM_MAX_SUPPORTED_DEVICE_INFO;
 
        for (i = 0; i < max_device; i++) {
-               ATOM_CONNECTOR_INFO_I2C ci =
-                   supported_devices->info.asConnInfo[i];
+               ATOM_CONNECTOR_INFO_I2C ci;
+
+               if (frev > 1)
+                       ci = supported_devices->info_2d1.asConnInfo[i];
+               else
+                       ci = supported_devices->info.asConnInfo[i];
 
                bios_connectors[i].valid = false;
 
index 112438d965ffbefd4fa2cce5f246cc03a63759f9..6e1fd6985ffcb730eb7057c4509aec971dfa8266 100644 (file)
@@ -288,17 +288,23 @@ static struct ttm_pool_type *ttm_pool_select_type(struct ttm_pool *pool,
                                                  enum ttm_caching caching,
                                                  unsigned int order)
 {
-       if (pool->use_dma_alloc || pool->nid != NUMA_NO_NODE)
+       if (pool->use_dma_alloc)
                return &pool->caching[caching].orders[order];
 
 #ifdef CONFIG_X86
        switch (caching) {
        case ttm_write_combined:
+               if (pool->nid != NUMA_NO_NODE)
+                       return &pool->caching[caching].orders[order];
+
                if (pool->use_dma32)
                        return &global_dma32_write_combined[order];
 
                return &global_write_combined[order];
        case ttm_uncached:
+               if (pool->nid != NUMA_NO_NODE)
+                       return &pool->caching[caching].orders[order];
+
                if (pool->use_dma32)
                        return &global_dma32_uncached[order];
 
@@ -566,11 +572,17 @@ void ttm_pool_init(struct ttm_pool *pool, struct device *dev,
        pool->use_dma_alloc = use_dma_alloc;
        pool->use_dma32 = use_dma32;
 
-       if (use_dma_alloc || nid != NUMA_NO_NODE) {
-               for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i)
-                       for (j = 0; j < NR_PAGE_ORDERS; ++j)
-                               ttm_pool_type_init(&pool->caching[i].orders[j],
-                                                  pool, i, j);
+       for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) {
+               for (j = 0; j < NR_PAGE_ORDERS; ++j) {
+                       struct ttm_pool_type *pt;
+
+                       /* Initialize only pool types which are actually used */
+                       pt = ttm_pool_select_type(pool, i, j);
+                       if (pt != &pool->caching[i].orders[j])
+                               continue;
+
+                       ttm_pool_type_init(pt, pool, i, j);
+               }
        }
 }
 EXPORT_SYMBOL(ttm_pool_init);
@@ -599,10 +611,16 @@ void ttm_pool_fini(struct ttm_pool *pool)
 {
        unsigned int i, j;
 
-       if (pool->use_dma_alloc || pool->nid != NUMA_NO_NODE) {
-               for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i)
-                       for (j = 0; j < NR_PAGE_ORDERS; ++j)
-                               ttm_pool_type_fini(&pool->caching[i].orders[j]);
+       for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) {
+               for (j = 0; j < NR_PAGE_ORDERS; ++j) {
+                       struct ttm_pool_type *pt;
+
+                       pt = ttm_pool_select_type(pool, i, j);
+                       if (pt != &pool->caching[i].orders[j])
+                               continue;
+
+                       ttm_pool_type_fini(pt);
+               }
        }
 
        /* We removed the pool types from the LRU, but we need to also make sure
index 578a7c37f00bd7a3c8a5f1d5e93d4cd80fdc6cc9..d776e3f87064fa2e86387fb69a0570259ac95fe7 100644 (file)
@@ -92,7 +92,7 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
         */
        if (bdev->pool.use_dma_alloc && cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
                page_flags |= TTM_TT_FLAG_DECRYPTED;
-               drm_info(ddev, "TT memory decryption enabled.");
+               drm_info_once(ddev, "TT memory decryption enabled.");
        }
 
        bo->ttm = bdev->funcs->ttm_tt_create(bo, page_flags);
index 2e04f6cb661e4f42eeaaef3c5d7fcdaee501d457..ce6b2fb341d1f8a85bab6f0ed19fd3ccde39757b 100644 (file)
@@ -105,7 +105,6 @@ v3d_irq(int irq, void *arg)
                struct v3d_file_priv *file = v3d->bin_job->base.file->driver_priv;
                u64 runtime = local_clock() - file->start_ns[V3D_BIN];
 
-               file->enabled_ns[V3D_BIN] += local_clock() - file->start_ns[V3D_BIN];
                file->jobs_sent[V3D_BIN]++;
                v3d->queue[V3D_BIN].jobs_sent++;
 
@@ -126,7 +125,6 @@ v3d_irq(int irq, void *arg)
                struct v3d_file_priv *file = v3d->render_job->base.file->driver_priv;
                u64 runtime = local_clock() - file->start_ns[V3D_RENDER];
 
-               file->enabled_ns[V3D_RENDER] += local_clock() - file->start_ns[V3D_RENDER];
                file->jobs_sent[V3D_RENDER]++;
                v3d->queue[V3D_RENDER].jobs_sent++;
 
@@ -147,7 +145,6 @@ v3d_irq(int irq, void *arg)
                struct v3d_file_priv *file = v3d->csd_job->base.file->driver_priv;
                u64 runtime = local_clock() - file->start_ns[V3D_CSD];
 
-               file->enabled_ns[V3D_CSD] += local_clock() - file->start_ns[V3D_CSD];
                file->jobs_sent[V3D_CSD]++;
                v3d->queue[V3D_CSD].jobs_sent++;
 
@@ -195,7 +192,6 @@ v3d_hub_irq(int irq, void *arg)
                struct v3d_file_priv *file = v3d->tfu_job->base.file->driver_priv;
                u64 runtime = local_clock() - file->start_ns[V3D_TFU];
 
-               file->enabled_ns[V3D_TFU] += local_clock() - file->start_ns[V3D_TFU];
                file->jobs_sent[V3D_TFU]++;
                v3d->queue[V3D_TFU].jobs_sent++;
 
index c52c7bf1485b1fa95b1e9ca3f1e05135167a8c5c..717d624e9a052298d5d5070551e909cc65ee0cc5 100644 (file)
@@ -456,8 +456,10 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
                .no_wait_gpu = false
        };
        u32 j, initial_line = dst_offset / dst_stride;
-       struct vmw_bo_blit_line_data d;
+       struct vmw_bo_blit_line_data d = {0};
        int ret = 0;
+       struct page **dst_pages = NULL;
+       struct page **src_pages = NULL;
 
        /* Buffer objects need to be either pinned or reserved: */
        if (!(dst->pin_count))
@@ -477,12 +479,35 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
                        return ret;
        }
 
+       if (!src->ttm->pages && src->ttm->sg) {
+               src_pages = kvmalloc_array(src->ttm->num_pages,
+                                          sizeof(struct page *), GFP_KERNEL);
+               if (!src_pages)
+                       return -ENOMEM;
+               ret = drm_prime_sg_to_page_array(src->ttm->sg, src_pages,
+                                                src->ttm->num_pages);
+               if (ret)
+                       goto out;
+       }
+       if (!dst->ttm->pages && dst->ttm->sg) {
+               dst_pages = kvmalloc_array(dst->ttm->num_pages,
+                                          sizeof(struct page *), GFP_KERNEL);
+               if (!dst_pages) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               ret = drm_prime_sg_to_page_array(dst->ttm->sg, dst_pages,
+                                                dst->ttm->num_pages);
+               if (ret)
+                       goto out;
+       }
+
        d.mapped_dst = 0;
        d.mapped_src = 0;
        d.dst_addr = NULL;
        d.src_addr = NULL;
-       d.dst_pages = dst->ttm->pages;
-       d.src_pages = src->ttm->pages;
+       d.dst_pages = dst->ttm->pages ? dst->ttm->pages : dst_pages;
+       d.src_pages = src->ttm->pages ? src->ttm->pages : src_pages;
        d.dst_num_pages = PFN_UP(dst->resource->size);
        d.src_num_pages = PFN_UP(src->resource->size);
        d.dst_prot = ttm_io_prot(dst, dst->resource, PAGE_KERNEL);
@@ -504,6 +529,10 @@ out:
                kunmap_atomic(d.src_addr);
        if (d.dst_addr)
                kunmap_atomic(d.dst_addr);
+       if (src_pages)
+               kvfree(src_pages);
+       if (dst_pages)
+               kvfree(dst_pages);
 
        return ret;
 }
index bfd41ce3c8f4fca1f5a659e4513e08f72ea95966..00144632c600ebb6a63ab80c55eae90eed95375f 100644 (file)
@@ -204,6 +204,7 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv,
                             VMW_BO_DOMAIN_VRAM,
                             VMW_BO_DOMAIN_VRAM);
        buf->places[0].lpfn = PFN_UP(bo->resource->size);
+       buf->busy_places[0].lpfn = PFN_UP(bo->resource->size);
        ret = ttm_bo_validate(bo, &buf->placement, &ctx);
 
        /* For some reason we didn't end up at the start of vram */
@@ -377,7 +378,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv,
 {
        struct ttm_operation_ctx ctx = {
                .interruptible = params->bo_type != ttm_bo_type_kernel,
-               .no_wait_gpu = false
+               .no_wait_gpu = false,
+               .resv = params->resv,
        };
        struct ttm_device *bdev = &dev_priv->bdev;
        struct drm_device *vdev = &dev_priv->drm;
@@ -394,8 +396,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv,
 
        vmw_bo_placement_set(vmw_bo, params->domain, params->busy_domain);
        ret = ttm_bo_init_reserved(bdev, &vmw_bo->tbo, params->bo_type,
-                                  &vmw_bo->placement, 0, &ctx, NULL,
-                                  NULL, destroy);
+                                  &vmw_bo->placement, 0, &ctx,
+                                  params->sg, params->resv, destroy);
        if (unlikely(ret))
                return ret;
 
index 0d496dc9c6af7a352c0432f50f4dd9be37448b5e..f349642e6190d6933031d08ccd7f353231f0f1da 100644 (file)
@@ -55,6 +55,8 @@ struct vmw_bo_params {
        enum ttm_bo_type bo_type;
        size_t size;
        bool pin;
+       struct dma_resv *resv;
+       struct sg_table *sg;
 };
 
 /**
index 0a304706e01322a6372727a27eb3fd0330471b31..58fb40c93100a84ec8b1dd769f35ab31c00bd0dc 100644 (file)
@@ -1628,6 +1628,7 @@ static const struct drm_driver driver = {
 
        .prime_fd_to_handle = vmw_prime_fd_to_handle,
        .prime_handle_to_fd = vmw_prime_handle_to_fd,
+       .gem_prime_import_sg_table = vmw_prime_import_sg_table,
 
        .fops = &vmwgfx_driver_fops,
        .name = VMWGFX_DRIVER_NAME,
index 12efecc17df664968056906da40cdd46b5665ddf..b019a1a1787af59e3fca37f560db905d7b2b6ab0 100644 (file)
@@ -1130,6 +1130,9 @@ extern int vmw_prime_handle_to_fd(struct drm_device *dev,
                                  struct drm_file *file_priv,
                                  uint32_t handle, uint32_t flags,
                                  int *prime_fd);
+struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev,
+                                                struct dma_buf_attachment *attach,
+                                                struct sg_table *table);
 
 /*
  * MemoryOBject management -  vmwgfx_mob.c
index 2a0cda324703147ef36ff83cd891c70c3395c11d..5efc6a766f64e467a68223376b2a97aa62b278e6 100644 (file)
@@ -991,7 +991,7 @@ static int vmw_event_fence_action_create(struct drm_file *file_priv,
        }
 
        event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED;
-       event->event.base.length = sizeof(*event);
+       event->event.base.length = sizeof(event->event);
        event->event.user_data = user_data;
 
        ret = drm_event_reserve_init(dev, file_priv, &event->base, &event->event.base);
index 12787bb9c111d10db997b9db650c6bb1069c26ef..d6bcaf078b1f40bbf75bdfb63fd1e00b7901e20f 100644 (file)
@@ -149,6 +149,38 @@ out_no_bo:
        return ret;
 }
 
+struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev,
+                                                struct dma_buf_attachment *attach,
+                                                struct sg_table *table)
+{
+       int ret;
+       struct vmw_private *dev_priv = vmw_priv(dev);
+       struct drm_gem_object *gem = NULL;
+       struct vmw_bo *vbo;
+       struct vmw_bo_params params = {
+               .domain = (dev_priv->has_mob) ? VMW_BO_DOMAIN_SYS : VMW_BO_DOMAIN_VRAM,
+               .busy_domain = VMW_BO_DOMAIN_SYS,
+               .bo_type = ttm_bo_type_sg,
+               .size = attach->dmabuf->size,
+               .pin = false,
+               .resv = attach->dmabuf->resv,
+               .sg = table,
+
+       };
+
+       dma_resv_lock(params.resv, NULL);
+
+       ret = vmw_bo_create(dev_priv, &params, &vbo);
+       if (ret != 0)
+               goto out_no_bo;
+
+       vbo->tbo.base.funcs = &vmw_gem_object_funcs;
+
+       gem = &vbo->tbo.base;
+out_no_bo:
+       dma_resv_unlock(params.resv);
+       return gem;
+}
 
 int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *filp)
index cd4925346ed45a1c10ae4e9d9b13c0066c71f168..84ae4e10a2ebec20c52a7eb42ea5455a0d22dfa5 100644 (file)
@@ -933,6 +933,7 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
 int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
                             struct drm_atomic_state *state)
 {
+       struct vmw_private *vmw = vmw_priv(crtc->dev);
        struct drm_crtc_state *new_state = drm_atomic_get_new_crtc_state(state,
                                                                         crtc);
        struct vmw_display_unit *du = vmw_crtc_to_du(new_state->crtc);
@@ -940,9 +941,13 @@ int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
        bool has_primary = new_state->plane_mask &
                           drm_plane_mask(crtc->primary);
 
-       /* We always want to have an active plane with an active CRTC */
-       if (has_primary != new_state->enable)
-               return -EINVAL;
+       /*
+        * This is fine in general, but broken userspace might expect
+        * some actual rendering so give a clue as why it's blank.
+        */
+       if (new_state->enable && !has_primary)
+               drm_dbg_driver(&vmw->drm,
+                              "CRTC without a primary plane will be blank.\n");
 
 
        if (new_state->connector_mask != connector_mask &&
index a94947b588e85f2c764aab60e11a84e59dd2a2ea..19a843da87b789b62279ecb9dccb8b2ddb19fe2f 100644 (file)
@@ -243,10 +243,10 @@ struct vmw_framebuffer_bo {
 
 
 static const uint32_t __maybe_unused vmw_primary_plane_formats[] = {
-       DRM_FORMAT_XRGB1555,
-       DRM_FORMAT_RGB565,
        DRM_FORMAT_XRGB8888,
        DRM_FORMAT_ARGB8888,
+       DRM_FORMAT_RGB565,
+       DRM_FORMAT_XRGB1555,
 };
 
 static const uint32_t __maybe_unused vmw_cursor_plane_formats[] = {
index 2d72a5ee7c0c710339d5d25c0a9376745a90f7af..c99cad444991579f6e665453b74f56cb35de2e15 100644 (file)
@@ -75,8 +75,12 @@ int vmw_prime_fd_to_handle(struct drm_device *dev,
                           int fd, u32 *handle)
 {
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+       int ret = ttm_prime_fd_to_handle(tfile, fd, handle);
 
-       return ttm_prime_fd_to_handle(tfile, fd, handle);
+       if (ret)
+               ret = drm_gem_prime_fd_to_handle(dev, file_priv, fd, handle);
+
+       return ret;
 }
 
 int vmw_prime_handle_to_fd(struct drm_device *dev,
@@ -85,5 +89,12 @@ int vmw_prime_handle_to_fd(struct drm_device *dev,
                           int *prime_fd)
 {
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
-       return ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd);
+       int ret;
+
+       if (handle > VMWGFX_NUM_MOB)
+               ret = ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd);
+       else
+               ret = drm_gem_prime_handle_to_fd(dev, file_priv, handle, flags, prime_fd);
+
+       return ret;
 }
index 4d23d0a70bcb7ef4901e9128b84cd7112ae8913a..621d98b376bbbc4b40cef6b9c6759b975610dd56 100644 (file)
@@ -188,13 +188,18 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
        switch (dev_priv->map_mode) {
        case vmw_dma_map_bind:
        case vmw_dma_map_populate:
-               vsgt->sgt = &vmw_tt->sgt;
-               ret = sg_alloc_table_from_pages_segment(
-                       &vmw_tt->sgt, vsgt->pages, vsgt->num_pages, 0,
-                       (unsigned long)vsgt->num_pages << PAGE_SHIFT,
-                       dma_get_max_seg_size(dev_priv->drm.dev), GFP_KERNEL);
-               if (ret)
-                       goto out_sg_alloc_fail;
+               if (vmw_tt->dma_ttm.page_flags  & TTM_TT_FLAG_EXTERNAL) {
+                       vsgt->sgt = vmw_tt->dma_ttm.sg;
+               } else {
+                       vsgt->sgt = &vmw_tt->sgt;
+                       ret = sg_alloc_table_from_pages_segment(&vmw_tt->sgt,
+                               vsgt->pages, vsgt->num_pages, 0,
+                               (unsigned long)vsgt->num_pages << PAGE_SHIFT,
+                               dma_get_max_seg_size(dev_priv->drm.dev),
+                               GFP_KERNEL);
+                       if (ret)
+                               goto out_sg_alloc_fail;
+               }
 
                ret = vmw_ttm_map_for_dma(vmw_tt);
                if (unlikely(ret != 0))
@@ -209,8 +214,9 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
        return 0;
 
 out_map_fail:
-       sg_free_table(vmw_tt->vsgt.sgt);
-       vmw_tt->vsgt.sgt = NULL;
+       drm_warn(&dev_priv->drm, "VSG table map failed!");
+       sg_free_table(vsgt->sgt);
+       vsgt->sgt = NULL;
 out_sg_alloc_fail:
        return ret;
 }
@@ -356,15 +362,17 @@ static void vmw_ttm_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)
 static int vmw_ttm_populate(struct ttm_device *bdev,
                            struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
 {
-       int ret;
+       bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0;
 
-       /* TODO: maybe completely drop this ? */
        if (ttm_tt_is_populated(ttm))
                return 0;
 
-       ret = ttm_pool_alloc(&bdev->pool, ttm, ctx);
+       if (external && ttm->sg)
+               return  drm_prime_sg_to_dma_addr_array(ttm->sg,
+                                                      ttm->dma_address,
+                                                      ttm->num_pages);
 
-       return ret;
+       return ttm_pool_alloc(&bdev->pool, ttm, ctx);
 }
 
 static void vmw_ttm_unpopulate(struct ttm_device *bdev,
@@ -372,6 +380,10 @@ static void vmw_ttm_unpopulate(struct ttm_device *bdev,
 {
        struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt,
                                                 dma_ttm);
+       bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0;
+
+       if (external)
+               return;
 
        vmw_ttm_unbind(bdev, ttm);
 
@@ -390,6 +402,7 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo,
 {
        struct vmw_ttm_tt *vmw_be;
        int ret;
+       bool external = bo->type == ttm_bo_type_sg;
 
        vmw_be = kzalloc(sizeof(*vmw_be), GFP_KERNEL);
        if (!vmw_be)
@@ -398,7 +411,10 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo,
        vmw_be->dev_priv = vmw_priv_from_ttm(bo->bdev);
        vmw_be->mob = NULL;
 
-       if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent)
+       if (external)
+               page_flags |= TTM_TT_FLAG_EXTERNAL | TTM_TT_FLAG_EXTERNAL_MAPPABLE;
+
+       if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent || external)
                ret = ttm_sg_tt_init(&vmw_be->dma_ttm, bo, page_flags,
                                     ttm_cached);
        else
index 420eba0e4be00b8d241bfe2d344837b262095785..854a7bb53567495a4cade766f62c985e8106a70d 100644 (file)
@@ -84,7 +84,8 @@ static inline struct drm_i915_private *kdev_to_i915(struct device *kdev)
 #define IS_ROCKETLAKE(dev_priv)        IS_PLATFORM(dev_priv, XE_ROCKETLAKE)
 #define IS_DG1(dev_priv)        IS_PLATFORM(dev_priv, XE_DG1)
 #define IS_ALDERLAKE_S(dev_priv) IS_PLATFORM(dev_priv, XE_ALDERLAKE_S)
-#define IS_ALDERLAKE_P(dev_priv) IS_PLATFORM(dev_priv, XE_ALDERLAKE_P)
+#define IS_ALDERLAKE_P(dev_priv) (IS_PLATFORM(dev_priv, XE_ALDERLAKE_P) || \
+                                 IS_PLATFORM(dev_priv, XE_ALDERLAKE_N))
 #define IS_XEHPSDV(dev_priv) (dev_priv && 0)
 #define IS_DG2(dev_priv)       IS_PLATFORM(dev_priv, XE_DG2)
 #define IS_PONTEVECCHIO(dev_priv) IS_PLATFORM(dev_priv, XE_PVC)
index b21da7b745a5e7cd6b3e34e4fb8d42a45b2b6466..a9c1f9885c6bb4d2727cbce81d5be93cb9458a38 100644 (file)
@@ -31,7 +31,7 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
 
        ret = ttm_bo_reserve(&bo->ttm, true, false, NULL);
        if (ret)
-               return ret;
+               goto err;
 
        if (!(bo->flags & XE_BO_SCANOUT_BIT)) {
                /*
@@ -42,12 +42,16 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
                 */
                if (XE_IOCTL_DBG(i915, !list_empty(&bo->ttm.base.gpuva.list))) {
                        ttm_bo_unreserve(&bo->ttm);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto err;
                }
                bo->flags |= XE_BO_SCANOUT_BIT;
        }
        ttm_bo_unreserve(&bo->ttm);
+       return 0;
 
+err:
+       xe_bo_put(bo);
        return ret;
 }
 
index a0afe1ba6dd5ce2cb6c3dfd53b60874ebb9c747c..f9705430ada93057c3094c1cb20ec400ae64ffdd 100644 (file)
@@ -378,7 +378,9 @@ static int gt_fw_domain_init(struct xe_gt *gt)
                         err);
 
        /* Initialize CCS mode sysfs after early initialization of HW engines */
-       xe_gt_ccs_mode_sysfs_init(gt);
+       err = xe_gt_ccs_mode_sysfs_init(gt);
+       if (err)
+               goto err_force_wake;
 
        /*
         * Stash hardware-reported version.  Since this register does not exist
index 529fc286cd06c6d46bcfde3b39bcd0e0befb8b44..396aeb5b992424b24ceeabeee9d76581ef404dbe 100644 (file)
@@ -167,25 +167,20 @@ static void xe_gt_ccs_mode_sysfs_fini(struct drm_device *drm, void *arg)
  * and it is expected that there are no open drm clients while doing so.
  * The number of available compute slices is exposed to user through a per-gt
  * 'num_cslices' sysfs interface.
+ *
+ * Returns: Returns error value for failure and 0 for success.
  */
-void xe_gt_ccs_mode_sysfs_init(struct xe_gt *gt)
+int xe_gt_ccs_mode_sysfs_init(struct xe_gt *gt)
 {
        struct xe_device *xe = gt_to_xe(gt);
        int err;
 
        if (!xe_gt_ccs_mode_enabled(gt))
-               return;
+               return 0;
 
        err = sysfs_create_files(gt->sysfs, gt_ccs_mode_attrs);
-       if (err) {
-               drm_warn(&xe->drm, "Sysfs creation for ccs_mode failed err: %d\n", err);
-               return;
-       }
+       if (err)
+               return err;
 
-       err = drmm_add_action_or_reset(&xe->drm, xe_gt_ccs_mode_sysfs_fini, gt);
-       if (err) {
-               sysfs_remove_files(gt->sysfs, gt_ccs_mode_attrs);
-               drm_warn(&xe->drm, "%s: drmm_add_action_or_reset failed, err: %d\n",
-                        __func__, err);
-       }
+       return drmm_add_action_or_reset(&xe->drm, xe_gt_ccs_mode_sysfs_fini, gt);
 }
index f39975aaaab0db1c62e06cc912afd74d668b1303..f8779852cf0d26587e3b579f351dcdeaf93efa5d 100644 (file)
@@ -12,7 +12,7 @@
 #include "xe_platform_types.h"
 
 void xe_gt_apply_ccs_mode(struct xe_gt *gt);
-void xe_gt_ccs_mode_sysfs_init(struct xe_gt *gt);
+int xe_gt_ccs_mode_sysfs_init(struct xe_gt *gt);
 
 static inline bool xe_gt_ccs_mode_enabled(const struct xe_gt *gt)
 {
index 355edd4d758af7cf1e4c15daf00ed86bbd4de898..7f32547f94b266092afc75bd387f8b6b59f18cec 100644 (file)
@@ -1054,10 +1054,10 @@ static int process_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len)
                                                           adj_len);
                break;
        case XE_GUC_ACTION_GUC2PF_RELAY_FROM_VF:
-               ret = xe_guc_relay_process_guc2pf(&guc->relay, payload, adj_len);
+               ret = xe_guc_relay_process_guc2pf(&guc->relay, hxg, hxg_len);
                break;
        case XE_GUC_ACTION_GUC2VF_RELAY_FROM_PF:
-               ret = xe_guc_relay_process_guc2vf(&guc->relay, payload, adj_len);
+               ret = xe_guc_relay_process_guc2vf(&guc->relay, hxg, hxg_len);
                break;
        default:
                drm_err(&xe->drm, "unexpected action 0x%04x\n", action);
index b545f850087cd8b9a7ae0031a2feb1fadba9458b..6b9b1cbedd379e35f78d6b943d46991f85caefa5 100644 (file)
@@ -53,7 +53,6 @@ static int huc_alloc_gsc_pkt(struct xe_huc *huc)
        struct xe_gt *gt = huc_to_gt(huc);
        struct xe_device *xe = gt_to_xe(gt);
        struct xe_bo *bo;
-       int err;
 
        /* we use a single object for both input and output */
        bo = xe_bo_create_pin_map(xe, gt_to_tile(gt), NULL,
@@ -66,13 +65,7 @@ static int huc_alloc_gsc_pkt(struct xe_huc *huc)
 
        huc->gsc_pkt = bo;
 
-       err = drmm_add_action_or_reset(&xe->drm, free_gsc_pkt, huc);
-       if (err) {
-               free_gsc_pkt(&xe->drm, huc);
-               return err;
-       }
-
-       return 0;
+       return drmm_add_action_or_reset(&xe->drm, free_gsc_pkt, huc);
 }
 
 int xe_huc_init(struct xe_huc *huc)
index 62d1ef8867a84351ae7444d63113d8867dfbb0c5..32cd0c978aa289efadec2f047dec7dd08b103de3 100644 (file)
@@ -1577,6 +1577,16 @@ void xe_vm_close_and_put(struct xe_vm *vm)
                xe->usm.num_vm_in_fault_mode--;
        else if (!(vm->flags & XE_VM_FLAG_MIGRATION))
                xe->usm.num_vm_in_non_fault_mode--;
+
+       if (vm->usm.asid) {
+               void *lookup;
+
+               xe_assert(xe, xe->info.has_asid);
+               xe_assert(xe, !(vm->flags & XE_VM_FLAG_MIGRATION));
+
+               lookup = xa_erase(&xe->usm.asid_to_vm, vm->usm.asid);
+               xe_assert(xe, lookup == vm);
+       }
        mutex_unlock(&xe->usm.lock);
 
        for_each_tile(tile, xe, id)
@@ -1592,24 +1602,18 @@ static void vm_destroy_work_func(struct work_struct *w)
        struct xe_device *xe = vm->xe;
        struct xe_tile *tile;
        u8 id;
-       void *lookup;
 
        /* xe_vm_close_and_put was not called? */
        xe_assert(xe, !vm->size);
 
+       if (xe_vm_in_preempt_fence_mode(vm))
+               flush_work(&vm->preempt.rebind_work);
+
        mutex_destroy(&vm->snap_mutex);
 
-       if (!(vm->flags & XE_VM_FLAG_MIGRATION)) {
+       if (!(vm->flags & XE_VM_FLAG_MIGRATION))
                xe_device_mem_access_put(xe);
 
-               if (xe->info.has_asid && vm->usm.asid) {
-                       mutex_lock(&xe->usm.lock);
-                       lookup = xa_erase(&xe->usm.asid_to_vm, vm->usm.asid);
-                       xe_assert(xe, lookup == vm);
-                       mutex_unlock(&xe->usm.lock);
-               }
-       }
-
        for_each_tile(tile, xe, id)
                XE_WARN_ON(vm->pt_root[id]);
 
index e6a8b6d8eab707da539cbc209f205d0ef02bba67..3c3c497b6b91141bb2948b1a124b1a144f1a4fdf 100644 (file)
@@ -965,9 +965,7 @@ static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev,
                }
                break;
        case REPORT_TYPE_MOUSE:
-               workitem->reports_supported |= STD_MOUSE | HIDPP;
-               if (djrcv_dev->type == recvr_type_mouse_only)
-                       workitem->reports_supported |= MULTIMEDIA;
+               workitem->reports_supported |= STD_MOUSE | HIDPP | MULTIMEDIA;
                break;
        }
 }
index f9cceaeffd0814411d6024a3dd714444953a80db..da5ea5a23b087cde332ed28bf21a542c758e8919 100644 (file)
@@ -944,9 +944,11 @@ static void mcp2221_hid_unregister(void *ptr)
 /* This is needed to be sure hid_hw_stop() isn't called twice by the subsystem */
 static void mcp2221_remove(struct hid_device *hdev)
 {
+#if IS_REACHABLE(CONFIG_IIO)
        struct mcp2221 *mcp = hid_get_drvdata(hdev);
 
        cancel_delayed_work_sync(&mcp->init_work);
+#endif
 }
 
 #if IS_REACHABLE(CONFIG_IIO)
index ab5953fc24367afb075bd82756f57878e75d38c2..80e0f23c1c33ec698f107ee6f8ed942020142dbf 100644 (file)
@@ -481,10 +481,10 @@ static const struct joycon_ctlr_button_mapping n64con_button_mappings[] = {
        { BTN_TR,               JC_BTN_R,       },
        { BTN_TR2,              JC_BTN_LSTICK,  }, /* ZR */
        { BTN_START,            JC_BTN_PLUS,    },
-       { BTN_FORWARD,          JC_BTN_Y,       }, /* C UP */
-       { BTN_BACK,             JC_BTN_ZR,      }, /* C DOWN */
-       { BTN_LEFT,             JC_BTN_X,       }, /* C LEFT */
-       { BTN_RIGHT,            JC_BTN_MINUS,   }, /* C RIGHT */
+       { BTN_SELECT,           JC_BTN_Y,       }, /* C UP */
+       { BTN_X,                JC_BTN_ZR,      }, /* C DOWN */
+       { BTN_Y,                JC_BTN_X,       }, /* C LEFT */
+       { BTN_C,                JC_BTN_MINUS,   }, /* C RIGHT */
        { BTN_MODE,             JC_BTN_HOME,    },
        { BTN_Z,                JC_BTN_CAP,     },
        { /* sentinel */ },
index 2df1ab3c31cc54da812ee653face224f32e69fc2..d965382196c69e87cd79d1aad49deeab7da1bba5 100644 (file)
@@ -64,7 +64,6 @@
 /* flags */
 #define I2C_HID_STARTED                0
 #define I2C_HID_RESET_PENDING  1
-#define I2C_HID_READ_PENDING   2
 
 #define I2C_HID_PWR_ON         0x00
 #define I2C_HID_PWR_SLEEP      0x01
@@ -190,15 +189,10 @@ static int i2c_hid_xfer(struct i2c_hid *ihid,
                msgs[n].len = recv_len;
                msgs[n].buf = recv_buf;
                n++;
-
-               set_bit(I2C_HID_READ_PENDING, &ihid->flags);
        }
 
        ret = i2c_transfer(client->adapter, msgs, n);
 
-       if (recv_len)
-               clear_bit(I2C_HID_READ_PENDING, &ihid->flags);
-
        if (ret != n)
                return ret < 0 ? ret : -EIO;
 
@@ -556,9 +550,6 @@ static irqreturn_t i2c_hid_irq(int irq, void *dev_id)
 {
        struct i2c_hid *ihid = dev_id;
 
-       if (test_bit(I2C_HID_READ_PENDING, &ihid->flags))
-               return IRQ_HANDLED;
-
        i2c_hid_get_input(ihid);
 
        return IRQ_HANDLED;
@@ -735,12 +726,15 @@ static int i2c_hid_parse(struct hid_device *hid)
        mutex_lock(&ihid->reset_lock);
        do {
                ret = i2c_hid_start_hwreset(ihid);
-               if (ret)
+               if (ret == 0)
+                       ret = i2c_hid_finish_hwreset(ihid);
+               else
                        msleep(1000);
        } while (tries-- > 0 && ret);
+       mutex_unlock(&ihid->reset_lock);
 
        if (ret)
-               goto abort_reset;
+               return ret;
 
        use_override = i2c_hid_get_dmi_hid_report_desc_override(client->name,
                                                                &rsize);
@@ -750,11 +744,8 @@ static int i2c_hid_parse(struct hid_device *hid)
                i2c_hid_dbg(ihid, "Using a HID report descriptor override\n");
        } else {
                rdesc = kzalloc(rsize, GFP_KERNEL);
-
-               if (!rdesc) {
-                       ret = -ENOMEM;
-                       goto abort_reset;
-               }
+               if (!rdesc)
+                       return -ENOMEM;
 
                i2c_hid_dbg(ihid, "asking HID report descriptor\n");
 
@@ -763,23 +754,10 @@ static int i2c_hid_parse(struct hid_device *hid)
                                            rdesc, rsize);
                if (ret) {
                        hid_err(hid, "reading report descriptor failed\n");
-                       goto abort_reset;
+                       goto out;
                }
        }
 
-       /*
-        * Windows directly reads the report-descriptor after sending reset
-        * and then waits for resets completion afterwards. Some touchpads
-        * actually wait for the report-descriptor to be read before signalling
-        * reset completion.
-        */
-       ret = i2c_hid_finish_hwreset(ihid);
-abort_reset:
-       clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
-       mutex_unlock(&ihid->reset_lock);
-       if (ret)
-               goto out;
-
        i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc);
 
        ret = hid_parse_report(hid, rdesc, rsize);
index a49c6affd7c4c48cdd09e3bdcca95139d0c066b8..dd5fc60874ba1d4f507e99fb5f28d87c16fdca9b 100644 (file)
@@ -948,6 +948,7 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
        if (!dev)
                return NULL;
 
+       dev->devc = &pdev->dev;
        ishtp_device_init(dev);
 
        init_waitqueue_head(&dev->wait_hw_ready);
@@ -983,7 +984,6 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
        }
 
        dev->ops = &ish_hw_ops;
-       dev->devc = &pdev->dev;
        dev->mtu = IPC_PAYLOAD_SIZE - sizeof(struct ishtp_msg_hdr);
        return dev;
 }
index ff5c486a1dbb1fa4a17d0d3f74885a7e3a0a69ec..db0d1ac82910e558b8df2e4e7f1c1f6535a06eaf 100644 (file)
@@ -2200,13 +2200,18 @@ static int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs,
  * Returns negative errno, else the number of messages executed.
  *
  * Adapter lock must be held when calling this function. No debug logging
- * takes place. adap->algo->master_xfer existence isn't checked.
+ * takes place.
  */
 int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
        unsigned long orig_jiffies;
        int ret, try;
 
+       if (!adap->algo->master_xfer) {
+               dev_dbg(&adap->dev, "I2C level transfers not supported\n");
+               return -EOPNOTSUPP;
+       }
+
        if (WARN_ON(!msgs || num < 1))
                return -EINVAL;
 
@@ -2273,11 +2278,6 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
        int ret;
 
-       if (!adap->algo->master_xfer) {
-               dev_dbg(&adap->dev, "I2C level transfers not supported\n");
-               return -EOPNOTSUPP;
-       }
-
        /* REVISIT the fault reporting model here is weak:
         *
         *  - When we get an error after receiving N bytes from a slave,
index 61839be501c21a023790c15c40f55a48cd8d3da3..63c3566a533bd89429b0104a563f1acc72280ad7 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (c) 2014, Intel Corporation.
  */
 
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/iio/iio.h>
 #define MXC4005_REG_ZOUT_UPPER         0x07
 #define MXC4005_REG_ZOUT_LOWER         0x08
 
+#define MXC4005_REG_INT_MASK0          0x0A
+
 #define MXC4005_REG_INT_MASK1          0x0B
 #define MXC4005_REG_INT_MASK1_BIT_DRDYE        0x01
 
+#define MXC4005_REG_INT_CLR0           0x00
+
 #define MXC4005_REG_INT_CLR1           0x01
 #define MXC4005_REG_INT_CLR1_BIT_DRDYC 0x01
+#define MXC4005_REG_INT_CLR1_SW_RST    0x10
 
 #define MXC4005_REG_CONTROL            0x0D
 #define MXC4005_REG_CONTROL_MASK_FSR   GENMASK(6, 5)
@@ -39,6 +45,9 @@
 
 #define MXC4005_REG_DEVICE_ID          0x0E
 
+/* Datasheet does not specify a reset time, this is a conservative guess */
+#define MXC4005_RESET_TIME_US          2000
+
 enum mxc4005_axis {
        AXIS_X,
        AXIS_Y,
@@ -62,6 +71,8 @@ struct mxc4005_data {
                s64 timestamp __aligned(8);
        } scan;
        bool trigger_enabled;
+       unsigned int control;
+       unsigned int int_mask1;
 };
 
 /*
@@ -113,7 +124,9 @@ static bool mxc4005_is_readable_reg(struct device *dev, unsigned int reg)
 static bool mxc4005_is_writeable_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
+       case MXC4005_REG_INT_CLR0:
        case MXC4005_REG_INT_CLR1:
+       case MXC4005_REG_INT_MASK0:
        case MXC4005_REG_INT_MASK1:
        case MXC4005_REG_CONTROL:
                return true;
@@ -330,23 +343,20 @@ static int mxc4005_set_trigger_state(struct iio_trigger *trig,
 {
        struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
        struct mxc4005_data *data = iio_priv(indio_dev);
+       unsigned int val;
        int ret;
 
        mutex_lock(&data->mutex);
-       if (state) {
-               ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1,
-                                  MXC4005_REG_INT_MASK1_BIT_DRDYE);
-       } else {
-               ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1,
-                                  ~MXC4005_REG_INT_MASK1_BIT_DRDYE);
-       }
 
+       val = state ? MXC4005_REG_INT_MASK1_BIT_DRDYE : 0;
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, val);
        if (ret < 0) {
                mutex_unlock(&data->mutex);
                dev_err(data->dev, "failed to update reg_int_mask1");
                return ret;
        }
 
+       data->int_mask1 = val;
        data->trigger_enabled = state;
        mutex_unlock(&data->mutex);
 
@@ -382,6 +392,21 @@ static int mxc4005_chip_init(struct mxc4005_data *data)
 
        dev_dbg(data->dev, "MXC4005 chip id %02x\n", reg);
 
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
+                          MXC4005_REG_INT_CLR1_SW_RST);
+       if (ret < 0)
+               return dev_err_probe(data->dev, ret, "resetting chip\n");
+
+       fsleep(MXC4005_RESET_TIME_US);
+
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);
+       if (ret < 0)
+               return dev_err_probe(data->dev, ret, "writing INT_MASK0\n");
+
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, 0);
+       if (ret < 0)
+               return dev_err_probe(data->dev, ret, "writing INT_MASK1\n");
+
        return 0;
 }
 
@@ -469,6 +494,58 @@ static int mxc4005_probe(struct i2c_client *client)
        return devm_iio_device_register(&client->dev, indio_dev);
 }
 
+static int mxc4005_suspend(struct device *dev)
+{
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct mxc4005_data *data = iio_priv(indio_dev);
+       int ret;
+
+       /* Save control to restore it on resume */
+       ret = regmap_read(data->regmap, MXC4005_REG_CONTROL, &data->control);
+       if (ret < 0)
+               dev_err(data->dev, "failed to read reg_control\n");
+
+       return ret;
+}
+
+static int mxc4005_resume(struct device *dev)
+{
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct mxc4005_data *data = iio_priv(indio_dev);
+       int ret;
+
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
+                          MXC4005_REG_INT_CLR1_SW_RST);
+       if (ret) {
+               dev_err(data->dev, "failed to reset chip: %d\n", ret);
+               return ret;
+       }
+
+       fsleep(MXC4005_RESET_TIME_US);
+
+       ret = regmap_write(data->regmap, MXC4005_REG_CONTROL, data->control);
+       if (ret) {
+               dev_err(data->dev, "failed to restore control register\n");
+               return ret;
+       }
+
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);
+       if (ret) {
+               dev_err(data->dev, "failed to restore interrupt 0 mask\n");
+               return ret;
+       }
+
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, data->int_mask1);
+       if (ret) {
+               dev_err(data->dev, "failed to restore interrupt 1 mask\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(mxc4005_pm_ops, mxc4005_suspend, mxc4005_resume);
+
 static const struct acpi_device_id mxc4005_acpi_match[] = {
        {"MXC4005",     0},
        {"MXC6655",     0},
@@ -496,6 +573,7 @@ static struct i2c_driver mxc4005_driver = {
                .name = MXC4005_DRV_NAME,
                .acpi_match_table = mxc4005_acpi_match,
                .of_match_table = mxc4005_of_match,
+               .pm = pm_sleep_ptr(&mxc4005_pm_ops),
        },
        .probe          = mxc4005_probe,
        .id_table       = mxc4005_id,
index 01f55cc902faad356acb1e3f52ea80ea500a4bdb..060a21c70460d290811c28fc9325a6e42df9bb01 100644 (file)
@@ -1289,6 +1289,7 @@ static int adis16475_config_sync_mode(struct adis16475 *st)
        struct device *dev = &st->adis.spi->dev;
        const struct adis16475_sync *sync;
        u32 sync_mode;
+       u16 val;
 
        /* default to internal clk */
        st->clk_freq = st->info->int_clk * 1000;
@@ -1350,8 +1351,9 @@ static int adis16475_config_sync_mode(struct adis16475 *st)
         * I'm keeping this for simplicity and avoiding extra variables
         * in chip_info.
         */
+       val = ADIS16475_SYNC_MODE(sync->sync_mode);
        ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
-                                ADIS16475_SYNC_MODE_MASK, sync->sync_mode);
+                                ADIS16475_SYNC_MODE_MASK, val);
        if (ret)
                return ret;
 
index fe8734468ed352589a0d09ddc9c3a3509b3d3fad..62e9e93d915dc8662b672b4aecb44d3ebf3e8081 100644 (file)
@@ -1233,6 +1233,7 @@ const struct bmp280_chip_info bmp380_chip_info = {
        .chip_id = bmp380_chip_ids,
        .num_chip_id = ARRAY_SIZE(bmp380_chip_ids),
        .regmap_config = &bmp380_regmap_config,
+       .spi_read_extra_byte = true,
        .start_up_time = 2000,
        .channels = bmp380_channels,
        .num_channels = 2,
index a444d4b2978b581ed8f4cd63b6821e23a45a0560..4e19ea0b4d398404340338db851b3033db8ab816 100644 (file)
@@ -96,15 +96,10 @@ static int bmp280_spi_probe(struct spi_device *spi)
 
        chip_info = spi_get_device_match_data(spi);
 
-       switch (chip_info->chip_id[0]) {
-       case BMP380_CHIP_ID:
-       case BMP390_CHIP_ID:
+       if (chip_info->spi_read_extra_byte)
                bmp_regmap_bus = &bmp380_regmap_bus;
-               break;
-       default:
+       else
                bmp_regmap_bus = &bmp280_regmap_bus;
-               break;
-       }
 
        regmap = devm_regmap_init(&spi->dev,
                                  bmp_regmap_bus,
@@ -127,7 +122,7 @@ static const struct of_device_id bmp280_of_spi_match[] = {
        { .compatible = "bosch,bmp180", .data = &bmp180_chip_info },
        { .compatible = "bosch,bmp181", .data = &bmp180_chip_info },
        { .compatible = "bosch,bmp280", .data = &bmp280_chip_info },
-       { .compatible = "bosch,bme280", .data = &bmp280_chip_info },
+       { .compatible = "bosch,bme280", .data = &bme280_chip_info },
        { .compatible = "bosch,bmp380", .data = &bmp380_chip_info },
        { .compatible = "bosch,bmp580", .data = &bmp580_chip_info },
        { },
@@ -139,7 +134,7 @@ static const struct spi_device_id bmp280_spi_id[] = {
        { "bmp180", (kernel_ulong_t)&bmp180_chip_info },
        { "bmp181", (kernel_ulong_t)&bmp180_chip_info },
        { "bmp280", (kernel_ulong_t)&bmp280_chip_info },
-       { "bme280", (kernel_ulong_t)&bmp280_chip_info },
+       { "bme280", (kernel_ulong_t)&bme280_chip_info },
        { "bmp380", (kernel_ulong_t)&bmp380_chip_info },
        { "bmp580", (kernel_ulong_t)&bmp580_chip_info },
        { }
index 4012387d79565631e9c8fdd0152f859c80eac485..5812a344ed8e889c441e9b21fc623f98a2e23333 100644 (file)
@@ -423,6 +423,7 @@ struct bmp280_chip_info {
        int num_chip_id;
 
        const struct regmap_config *regmap_config;
+       bool spi_read_extra_byte;
 
        const struct iio_chan_spec *channels;
        int num_channels;
index bf0df6ee4f7857b4ac8d9ca1c9789b7ef3e4afa9..07fb8d3c037f004ccd34c5393a95c48bffdd8298 100644 (file)
@@ -1026,23 +1026,26 @@ static void cm_reset_to_idle(struct cm_id_private *cm_id_priv)
        }
 }
 
-static noinline void cm_destroy_id_wait_timeout(struct ib_cm_id *cm_id)
+static noinline void cm_destroy_id_wait_timeout(struct ib_cm_id *cm_id,
+                                               enum ib_cm_state old_state)
 {
        struct cm_id_private *cm_id_priv;
 
        cm_id_priv = container_of(cm_id, struct cm_id_private, id);
-       pr_err("%s: cm_id=%p timed out. state=%d refcnt=%d\n", __func__,
-              cm_id, cm_id->state, refcount_read(&cm_id_priv->refcount));
+       pr_err("%s: cm_id=%p timed out. state %d -> %d, refcnt=%d\n", __func__,
+              cm_id, old_state, cm_id->state, refcount_read(&cm_id_priv->refcount));
 }
 
 static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
 {
        struct cm_id_private *cm_id_priv;
+       enum ib_cm_state old_state;
        struct cm_work *work;
        int ret;
 
        cm_id_priv = container_of(cm_id, struct cm_id_private, id);
        spin_lock_irq(&cm_id_priv->lock);
+       old_state = cm_id->state;
 retest:
        switch (cm_id->state) {
        case IB_CM_LISTEN:
@@ -1151,7 +1154,7 @@ retest:
                                                  msecs_to_jiffies(
                                                  CM_DESTROY_ID_WAIT_TIMEOUT));
                if (!ret) /* timeout happened */
-                       cm_destroy_id_wait_timeout(cm_id);
+                       cm_destroy_id_wait_timeout(cm_id, old_state);
        } while (!ret);
 
        while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
index 0c3c4e64812c58cf8457dbaffeb7a28e31cebad1..3e43687a7f6f7313f4031955b1ad03fbc22b8bf9 100644 (file)
@@ -188,7 +188,8 @@ static int process_pma_cmd(struct mlx5_ib_dev *dev, u32 port_num,
                mdev = dev->mdev;
                mdev_port_num = 1;
        }
-       if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1) {
+       if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1 &&
+           !mlx5_core_mp_enabled(mdev)) {
                /* set local port to one for Function-Per-Port HCA. */
                mdev = dev->mdev;
                mdev_port_num = 1;
index ae466e72fc43b3811908cff9f92f6f94c3fb443e..255677bc12b2ab4006f7dd4b6a9f39ae5336ecb4 100644 (file)
@@ -33,6 +33,8 @@ void rxe_dealloc(struct ib_device *ib_dev)
 
        if (rxe->tfm)
                crypto_free_shash(rxe->tfm);
+
+       mutex_destroy(&rxe->usdev_lock);
 }
 
 /* initialize rxe device parameters */
index f50848ed5575dbe143b159f5c16864fc0cc7b25c..6fadaddb2b908f0b0a2ed5cdd9c8382f08cacae8 100644 (file)
@@ -208,6 +208,7 @@ static const struct xpad_device {
        { 0x0738, 0xcb29, "Saitek Aviator Stick AV8R02", 0, XTYPE_XBOX360 },
        { 0x0738, 0xf738, "Super SFIV FightStick TE S", 0, XTYPE_XBOX360 },
        { 0x07ff, 0xffff, "Mad Catz GamePad", 0, XTYPE_XBOX360 },
+       { 0x0b05, 0x1a38, "ASUS ROG RAIKIRI", 0, XTYPE_XBOXONE },
        { 0x0c12, 0x0005, "Intec wireless", 0, XTYPE_XBOX },
        { 0x0c12, 0x8801, "Nyko Xbox Controller", 0, XTYPE_XBOX },
        { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX },
@@ -487,6 +488,7 @@ static const struct usb_device_id xpad_table[] = {
        { USB_DEVICE(0x0738, 0x4540) },         /* Mad Catz Beat Pad */
        XPAD_XBOXONE_VENDOR(0x0738),            /* Mad Catz FightStick TE 2 */
        XPAD_XBOX360_VENDOR(0x07ff),            /* Mad Catz Gamepad */
+       XPAD_XBOXONE_VENDOR(0x0b05),            /* ASUS controllers */
        XPAD_XBOX360_VENDOR(0x0c12),            /* Zeroplus X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x0e6f),            /* 0x0e6f Xbox 360 controllers */
        XPAD_XBOXONE_VENDOR(0x0e6f),            /* 0x0e6f Xbox One controllers */
index cda0c3ff5a288df0840011442442e0995330287a..2fbbaeb76d708284e1512ed89fc5a7806c177f1f 100644 (file)
@@ -132,7 +132,13 @@ static void __exit amimouse_remove(struct platform_device *pdev)
        input_unregister_device(dev);
 }
 
-static struct platform_driver amimouse_driver = {
+/*
+ * amimouse_remove() lives in .exit.text. For drivers registered via
+ * module_platform_driver_probe() this is ok because they cannot get unbound at
+ * runtime. So mark the driver struct with __refdata to prevent modpost
+ * triggering a section mismatch warning.
+ */
+static struct platform_driver amimouse_driver __refdata = {
        .remove_new = __exit_p(amimouse_remove),
        .driver   = {
                .name   = "amiga-mouse",
index 5d1010cafed8d3a3b65349dd58a0741d445ffcd7..7e9b996b47c833c59873520d28c723f7ca97d07a 100644 (file)
@@ -176,6 +176,8 @@ static struct icc_path *path_init(struct device *dev, struct icc_node *dst,
 
        path->num_nodes = num_nodes;
 
+       mutex_lock(&icc_bw_lock);
+
        for (i = num_nodes - 1; i >= 0; i--) {
                node->provider->users++;
                hlist_add_head(&path->reqs[i].req_node, &node->req_list);
@@ -186,6 +188,8 @@ static struct icc_path *path_init(struct device *dev, struct icc_node *dst,
                node = node->reverse;
        }
 
+       mutex_unlock(&icc_bw_lock);
+
        return path;
 }
 
@@ -792,12 +796,16 @@ void icc_put(struct icc_path *path)
                pr_err("%s: error (%d)\n", __func__, ret);
 
        mutex_lock(&icc_lock);
+       mutex_lock(&icc_bw_lock);
+
        for (i = 0; i < path->num_nodes; i++) {
                node = path->reqs[i].node;
                hlist_del(&path->reqs[i].req_node);
                if (!WARN_ON(!node->provider->users))
                        node->provider->users--;
        }
+
+       mutex_unlock(&icc_bw_lock);
        mutex_unlock(&icc_lock);
 
        kfree_const(path->name);
index 99824675ee3f495cb8adeabae6c01c185c3a60c1..654abb9ce08eedaa06dbe12945cc42d45e0844b0 100644 (file)
@@ -116,15 +116,6 @@ static struct qcom_icc_node xm_sdc2 = {
        .links = { X1E80100_SLAVE_A2NOC_SNOC },
 };
 
-static struct qcom_icc_node ddr_perf_mode_master = {
-       .name = "ddr_perf_mode_master",
-       .id = X1E80100_MASTER_DDR_PERF_MODE,
-       .channels = 1,
-       .buswidth = 4,
-       .num_links = 1,
-       .links = { X1E80100_SLAVE_DDR_PERF_MODE },
-};
-
 static struct qcom_icc_node qup0_core_master = {
        .name = "qup0_core_master",
        .id = X1E80100_MASTER_QUP_CORE_0,
@@ -688,14 +679,6 @@ static struct qcom_icc_node qns_a2noc_snoc = {
        .links = { X1E80100_MASTER_A2NOC_SNOC },
 };
 
-static struct qcom_icc_node ddr_perf_mode_slave = {
-       .name = "ddr_perf_mode_slave",
-       .id = X1E80100_SLAVE_DDR_PERF_MODE,
-       .channels = 1,
-       .buswidth = 4,
-       .num_links = 0,
-};
-
 static struct qcom_icc_node qup0_core_slave = {
        .name = "qup0_core_slave",
        .id = X1E80100_SLAVE_QUP_CORE_0,
@@ -1377,12 +1360,6 @@ static struct qcom_icc_bcm bcm_acv = {
        .nodes = { &ebi },
 };
 
-static struct qcom_icc_bcm bcm_acv_perf = {
-       .name = "ACV_PERF",
-       .num_nodes = 1,
-       .nodes = { &ddr_perf_mode_slave },
-};
-
 static struct qcom_icc_bcm bcm_ce0 = {
        .name = "CE0",
        .num_nodes = 1,
@@ -1583,18 +1560,15 @@ static const struct qcom_icc_desc x1e80100_aggre2_noc = {
 };
 
 static struct qcom_icc_bcm * const clk_virt_bcms[] = {
-       &bcm_acv_perf,
        &bcm_qup0,
        &bcm_qup1,
        &bcm_qup2,
 };
 
 static struct qcom_icc_node * const clk_virt_nodes[] = {
-       [MASTER_DDR_PERF_MODE] = &ddr_perf_mode_master,
        [MASTER_QUP_CORE_0] = &qup0_core_master,
        [MASTER_QUP_CORE_1] = &qup1_core_master,
        [MASTER_QUP_CORE_2] = &qup2_core_master,
-       [SLAVE_DDR_PERF_MODE] = &ddr_perf_mode_slave,
        [SLAVE_QUP_CORE_0] = &qup0_core_slave,
        [SLAVE_QUP_CORE_1] = &qup1_core_slave,
        [SLAVE_QUP_CORE_2] = &qup2_core_slave,
index 99d4b075df49e446ef04295ab73020ae7b8f74c5..76656fe0470d7dce8aa49b201f59562e189da148 100644 (file)
@@ -37,6 +37,7 @@ config IOMMUFD_TEST
        depends on DEBUG_KERNEL
        depends on FAULT_INJECTION
        depends on RUNTIME_TESTING_MENU
+       select IOMMUFD_DRIVER
        default n
        help
          This is dangerous, do not enable unless running
index 2a537cbfcb077246c0aee43a5b9f1885a3e0b5f2..5f7d3db3afd8248e43e6fc86b677fb0fdc587a84 100644 (file)
@@ -4567,13 +4567,8 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
                irqd_set_resend_when_in_progress(irq_get_irq_data(virq + i));
        }
 
-       if (err) {
-               if (i > 0)
-                       its_vpe_irq_domain_free(domain, virq, i);
-
-               its_lpi_free(bitmap, base, nr_ids);
-               its_free_prop_table(vprop_page);
-       }
+       if (err)
+               its_vpe_irq_domain_free(domain, virq, i);
 
        return err;
 }
index 01d2743444ec6cc7eec0945b69ba1c63195f09b1..3a989efae1420a0f2e5b965b55555fe8a85a4037 100644 (file)
@@ -137,7 +137,7 @@ void murmurhash3_128(const void *key, const int len, const u32 seed, void *out)
                        break;
                default:
                        break;
-               };
+               }
        }
        /* finalization */
 
index 56aa2a8b9d7153ac0792bbdc626ab5250cf074c7..7d0746b37c8ec791f111d6e589476eb2b500e9d4 100644 (file)
@@ -765,7 +765,7 @@ static struct table_device *open_table_device(struct mapped_device *md,
        return td;
 
 out_blkdev_put:
-       fput(bdev_file);
+       __fput_sync(bdev_file);
 out_free_td:
        kfree(td);
        return ERR_PTR(r);
@@ -778,7 +778,13 @@ static void close_table_device(struct table_device *td, struct mapped_device *md
 {
        if (md->disk->slave_dir)
                bd_unlink_disk_holder(td->dm_dev.bdev, md->disk);
-       fput(td->dm_dev.bdev_file);
+
+       /* Leverage async fput() if DMF_DEFERRED_REMOVE set */
+       if (unlikely(test_bit(DMF_DEFERRED_REMOVE, &md->flags)))
+               fput(td->dm_dev.bdev_file);
+       else
+               __fput_sync(td->dm_dev.bdev_file);
+
        put_dax(td->dm_dev.dax_dev);
        list_del(&td->list);
        kfree(td);
index 1a64364700eb0f3d3b93197f04c154c03fd3601a..0ad2ff9065aad0d31ca2be16e32629b5612ecfea 100644 (file)
@@ -1002,7 +1002,7 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
                } else {
                        pcr->card_removed |= SD_EXIST;
                        pcr->card_inserted &= ~SD_EXIST;
-                       if (PCI_PID(pcr) == PID_5261) {
+                       if ((PCI_PID(pcr) == PID_5261) || (PCI_PID(pcr) == PID_5264)) {
                                rtsx_pci_write_register(pcr, RTS5261_FW_STATUS,
                                        RTS5261_EXPRESS_LINK_FAIL_MASK, 0);
                                pcr->extra_caps |= EXTRA_CAPS_SD_EXPRESS;
index 572333ead5fb8b002b87957dfe1dc9ea26330efb..4bd4f32bcdabb8f98d2b764f04bb2ac9f8270d83 100644 (file)
@@ -758,15 +758,6 @@ static int at24_probe(struct i2c_client *client)
        }
        pm_runtime_enable(dev);
 
-       at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
-       if (IS_ERR(at24->nvmem)) {
-               pm_runtime_disable(dev);
-               if (!pm_runtime_status_suspended(dev))
-                       regulator_disable(at24->vcc_reg);
-               return dev_err_probe(dev, PTR_ERR(at24->nvmem),
-                                    "failed to register nvmem\n");
-       }
-
        /*
         * Perform a one-byte test read to verify that the chip is functional,
         * unless powering on the device is to be avoided during probe (i.e.
@@ -782,6 +773,15 @@ static int at24_probe(struct i2c_client *client)
                }
        }
 
+       at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
+       if (IS_ERR(at24->nvmem)) {
+               pm_runtime_disable(dev);
+               if (!pm_runtime_status_suspended(dev))
+                       regulator_disable(at24->vcc_reg);
+               return dev_err_probe(dev, PTR_ERR(at24->nvmem),
+                                    "failed to register nvmem\n");
+       }
+
        /* If this a SPD EEPROM, probe for DDR3 thermal sensor */
        if (cdata == &at24_data_spd)
                at24_probe_temp_sensor(client);
index aac36750d2c54a658debcca55063d2e2a02bf1ce..c3a6657dcd4a291a09d2f5abf1b0f1d740c10703 100644 (file)
 #define MEI_DEV_ID_ARL_S      0x7F68  /* Arrow Lake Point S */
 #define MEI_DEV_ID_ARL_H      0x7770  /* Arrow Lake Point H */
 
+#define MEI_DEV_ID_LNL_M      0xA870  /* Lunar Lake Point M */
+
 /*
  * MEI HW Section
  */
index b5757993c9b2af992c54468a75e630c080bcad61..7f59dd38c32f52dccf632fb4bb06066972d26862 100644 (file)
@@ -116,12 +116,14 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
        {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_P, MEI_ME_PCH15_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_N, MEI_ME_PCH15_CFG)},
 
-       {MEI_PCI_DEVICE(MEI_DEV_ID_RPL_S, MEI_ME_PCH15_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_RPL_S, MEI_ME_PCH15_SPS_CFG)},
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_MTL_M, MEI_ME_PCH15_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_ARL_S, MEI_ME_PCH15_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_ARL_H, MEI_ME_PCH15_CFG)},
 
+       {MEI_PCI_DEVICE(MEI_DEV_ID_LNL_M, MEI_ME_PCH15_CFG)},
+
        /* required last entry */
        {0, }
 };
index 6c9f00bcb94b1857588b3bc6a0ada02421d9f87a..b543e6b9f3cfd6542e744854fa6d20c1cbe7b216 100644 (file)
@@ -400,25 +400,40 @@ static void mei_vsc_remove(struct platform_device *pdev)
 static int mei_vsc_suspend(struct device *dev)
 {
        struct mei_device *mei_dev = dev_get_drvdata(dev);
+       struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
 
        mei_stop(mei_dev);
 
+       mei_disable_interrupts(mei_dev);
+
+       vsc_tp_free_irq(hw->tp);
+
        return 0;
 }
 
 static int mei_vsc_resume(struct device *dev)
 {
        struct mei_device *mei_dev = dev_get_drvdata(dev);
+       struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
        int ret;
 
-       ret = mei_restart(mei_dev);
+       ret = vsc_tp_request_irq(hw->tp);
        if (ret)
                return ret;
 
+       ret = mei_restart(mei_dev);
+       if (ret)
+               goto err_free;
+
        /* start timer if stopped in suspend */
        schedule_delayed_work(&mei_dev->timer_work, HZ);
 
        return 0;
+
+err_free:
+       vsc_tp_free_irq(hw->tp);
+
+       return ret;
 }
 
 static DEFINE_SIMPLE_DEV_PM_OPS(mei_vsc_pm_ops, mei_vsc_suspend, mei_vsc_resume);
index b1e4c23b31a32957c616f0edcdf74dc086c44a89..49abc95677cdac6a74d673cbf5444ccc82deee74 100644 (file)
@@ -236,8 +236,11 @@ static int mei_pxp_component_match(struct device *dev, int subcomponent,
 
        pdev = to_pci_dev(dev);
 
-       if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8) ||
-           pdev->vendor != PCI_VENDOR_ID_INTEL)
+       if (pdev->vendor != PCI_VENDOR_ID_INTEL)
+               return 0;
+
+       if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8) &&
+           pdev->class != (PCI_CLASS_DISPLAY_OTHER << 8))
                return 0;
 
        if (subcomponent != I915_COMPONENT_PXP)
index ecfb70cd057ca01eb33e544ef242ab1aee2cd25a..e6a98dba8a735ec88787d7c8577879b80b323bf7 100644 (file)
@@ -94,6 +94,27 @@ static const struct acpi_gpio_mapping vsc_tp_acpi_gpios[] = {
        {}
 };
 
+static irqreturn_t vsc_tp_isr(int irq, void *data)
+{
+       struct vsc_tp *tp = data;
+
+       atomic_inc(&tp->assert_cnt);
+
+       wake_up(&tp->xfer_wait);
+
+       return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t vsc_tp_thread_isr(int irq, void *data)
+{
+       struct vsc_tp *tp = data;
+
+       if (tp->event_notify)
+               tp->event_notify(tp->event_notify_context);
+
+       return IRQ_HANDLED;
+}
+
 /* wakeup firmware and wait for response */
 static int vsc_tp_wakeup_request(struct vsc_tp *tp)
 {
@@ -383,6 +404,37 @@ int vsc_tp_register_event_cb(struct vsc_tp *tp, vsc_tp_event_cb_t event_cb,
 }
 EXPORT_SYMBOL_NS_GPL(vsc_tp_register_event_cb, VSC_TP);
 
+/**
+ * vsc_tp_request_irq - request irq for vsc_tp device
+ * @tp: vsc_tp device handle
+ */
+int vsc_tp_request_irq(struct vsc_tp *tp)
+{
+       struct spi_device *spi = tp->spi;
+       struct device *dev = &spi->dev;
+       int ret;
+
+       irq_set_status_flags(spi->irq, IRQ_DISABLE_UNLAZY);
+       ret = request_threaded_irq(spi->irq, vsc_tp_isr, vsc_tp_thread_isr,
+                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                  dev_name(dev), tp);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+EXPORT_SYMBOL_NS_GPL(vsc_tp_request_irq, VSC_TP);
+
+/**
+ * vsc_tp_free_irq - free irq for vsc_tp device
+ * @tp: vsc_tp device handle
+ */
+void vsc_tp_free_irq(struct vsc_tp *tp)
+{
+       free_irq(tp->spi->irq, tp);
+}
+EXPORT_SYMBOL_NS_GPL(vsc_tp_free_irq, VSC_TP);
+
 /**
  * vsc_tp_intr_synchronize - synchronize vsc_tp interrupt
  * @tp: vsc_tp device handle
@@ -413,27 +465,6 @@ void vsc_tp_intr_disable(struct vsc_tp *tp)
 }
 EXPORT_SYMBOL_NS_GPL(vsc_tp_intr_disable, VSC_TP);
 
-static irqreturn_t vsc_tp_isr(int irq, void *data)
-{
-       struct vsc_tp *tp = data;
-
-       atomic_inc(&tp->assert_cnt);
-
-       return IRQ_WAKE_THREAD;
-}
-
-static irqreturn_t vsc_tp_thread_isr(int irq, void *data)
-{
-       struct vsc_tp *tp = data;
-
-       wake_up(&tp->xfer_wait);
-
-       if (tp->event_notify)
-               tp->event_notify(tp->event_notify_context);
-
-       return IRQ_HANDLED;
-}
-
 static int vsc_tp_match_any(struct acpi_device *adev, void *data)
 {
        struct acpi_device **__adev = data;
@@ -490,10 +521,9 @@ static int vsc_tp_probe(struct spi_device *spi)
        tp->spi = spi;
 
        irq_set_status_flags(spi->irq, IRQ_DISABLE_UNLAZY);
-       ret = devm_request_threaded_irq(dev, spi->irq, vsc_tp_isr,
-                                       vsc_tp_thread_isr,
-                                       IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                                       dev_name(dev), tp);
+       ret = request_threaded_irq(spi->irq, vsc_tp_isr, vsc_tp_thread_isr,
+                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                  dev_name(dev), tp);
        if (ret)
                return ret;
 
@@ -522,6 +552,8 @@ static int vsc_tp_probe(struct spi_device *spi)
 err_destroy_lock:
        mutex_destroy(&tp->mutex);
 
+       free_irq(spi->irq, tp);
+
        return ret;
 }
 
@@ -532,6 +564,8 @@ static void vsc_tp_remove(struct spi_device *spi)
        platform_device_unregister(tp->pdev);
 
        mutex_destroy(&tp->mutex);
+
+       free_irq(spi->irq, tp);
 }
 
 static const struct acpi_device_id vsc_tp_acpi_ids[] = {
index f9513ddc3e409350ffe871af1ad30268226e6225..14ca195cbddccf23b15c03556411dbef95a18715 100644 (file)
@@ -37,6 +37,9 @@ int vsc_tp_xfer(struct vsc_tp *tp, u8 cmd, const void *obuf, size_t olen,
 int vsc_tp_register_event_cb(struct vsc_tp *tp, vsc_tp_event_cb_t event_cb,
                             void *context);
 
+int vsc_tp_request_irq(struct vsc_tp *tp);
+void vsc_tp_free_irq(struct vsc_tp *tp);
+
 void vsc_tp_intr_enable(struct vsc_tp *tp);
 void vsc_tp_intr_disable(struct vsc_tp *tp);
 void vsc_tp_intr_synchronize(struct vsc_tp *tp);
index 9ad20e82785bcd6ade57d493e31152ecff334178..b21598a18f6da81568dedb0817bf74da55f81a15 100644 (file)
@@ -44,8 +44,6 @@ static struct pci_driver pvpanic_pci_driver = {
        .name =         "pvpanic-pci",
        .id_table =     pvpanic_pci_id_tbl,
        .probe =        pvpanic_pci_probe,
-       .driver = {
-               .dev_groups = pvpanic_dev_groups,
-       },
+       .dev_groups =   pvpanic_dev_groups,
 };
 module_pci_driver(pvpanic_pci_driver);
index b88d6dec209f5722df79c3d269070939aa2d72da..9a5f75163acaeef8226ee122dde79c60fd9b7d8c 100644 (file)
@@ -300,6 +300,7 @@ static void moxart_transfer_pio(struct moxart_host *host)
        remain = sgm->length;
        if (remain > host->data_len)
                remain = host->data_len;
+       sgm->consumed = 0;
 
        if (data->flags & MMC_DATA_WRITE) {
                while (remain > 0) {
index 668e0aceeebac9caecb84af355eb08d51c71de0b..e113b99a3eab592dfdd24bbd6c371c2756c2b6c9 100644 (file)
@@ -2694,6 +2694,11 @@ static __maybe_unused int sdhci_msm_runtime_suspend(struct device *dev)
        struct sdhci_host *host = dev_get_drvdata(dev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+       unsigned long flags;
+
+       spin_lock_irqsave(&host->lock, flags);
+       host->runtime_suspended = true;
+       spin_unlock_irqrestore(&host->lock, flags);
 
        /* Drop the performance vote */
        dev_pm_opp_set_rate(dev, 0);
@@ -2708,6 +2713,7 @@ static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev)
        struct sdhci_host *host = dev_get_drvdata(dev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+       unsigned long flags;
        int ret;
 
        ret = clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks),
@@ -2726,7 +2732,15 @@ static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev)
 
        dev_pm_opp_set_rate(dev, msm_host->clk_rate);
 
-       return sdhci_msm_ice_resume(msm_host);
+       ret = sdhci_msm_ice_resume(msm_host);
+       if (ret)
+               return ret;
+
+       spin_lock_irqsave(&host->lock, flags);
+       host->runtime_suspended = false;
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       return ret;
 }
 
 static const struct dev_pm_ops sdhci_msm_pm_ops = {
index 1d8f5a76096aeb3c836722b3f97226d7dd2c5201..f2e4a93ed1d61a22d4601fefe2a120caf2b19333 100644 (file)
@@ -626,6 +626,7 @@ static int th1520_execute_tuning(struct sdhci_host *host, u32 opcode)
 
        /* perform tuning */
        sdhci_start_tuning(host);
+       host->tuning_loop_count = 128;
        host->tuning_err = __sdhci_execute_tuning(host, opcode);
        if (host->tuning_err) {
                /* disable auto-tuning upon tuning error */
index 025b31aa712caa13fb16c7038fbe92122d3d2912..ef89ec382bfef9768a476006e70e95b15f65e099 100644 (file)
@@ -63,7 +63,7 @@ static int sdhci_pci_init_wakeup(struct sdhci_pci_chip *chip)
        if ((pm_flags & MMC_PM_KEEP_POWER) && (pm_flags & MMC_PM_WAKE_SDIO_IRQ))
                return device_wakeup_enable(&chip->pdev->dev);
        else if (!cap_cd_wake)
-               return device_wakeup_disable(&chip->pdev->dev);
+               device_wakeup_disable(&chip->pdev->dev);
 
        return 0;
 }
index 5887feb347a4e42aa1dcc779bc7f5b252402b16e..0de87bc63840546d8a11dfe959874a5af7835ac6 100644 (file)
@@ -900,7 +900,7 @@ static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd,
        config.name = compatible;
        config.id = NVMEM_DEVID_AUTO;
        config.owner = THIS_MODULE;
-       config.add_legacy_fixed_of_cells = true;
+       config.add_legacy_fixed_of_cells = !mtd_type_is_nand(mtd);
        config.type = NVMEM_TYPE_OTP;
        config.root_only = true;
        config.ignore_wp = true;
index a8d12c71f987be95817a69b4ee92c229ec8bf814..1b2ec0fec60c7a19e76f67dc5db47e98f4ad8a28 100644 (file)
@@ -857,7 +857,7 @@ static inline void brcmnand_read_data_bus(struct brcmnand_controller *ctrl,
        struct brcmnand_soc *soc = ctrl->soc;
        int i;
 
-       if (soc->read_data_bus) {
+       if (soc && soc->read_data_bus) {
                soc->read_data_bus(soc, flash_cache, buffer, fc_words);
        } else {
                for (i = 0; i < fc_words; i++)
index 5243fab9face0034ecf54838345624b816f91906..8db7fc424571116abb467def163d2f1725c49b9f 100644 (file)
@@ -53,7 +53,7 @@ static unsigned long doc_locations[] __initdata = {
        0xe8000, 0xea000, 0xec000, 0xee000,
 #endif
 #endif
-       0xffffffff };
+};
 
 static struct mtd_info *doclist = NULL;
 
@@ -1554,7 +1554,7 @@ static int __init init_nanddoc(void)
                if (ret < 0)
                        return ret;
        } else {
-               for (i = 0; (doc_locations[i] != 0xffffffff); i++) {
+               for (i = 0; i < ARRAY_SIZE(doc_locations); i++) {
                        doc_probe(doc_locations[i]);
                }
        }
index b079605c84d38204971834ea2c26d2858165b506..b8cff9240b286c7ac789bf4216611b54bee05dd3 100644 (file)
@@ -2815,7 +2815,7 @@ static int qcom_misc_cmd_type_exec(struct nand_chip *chip, const struct nand_sub
                              host->cfg0_raw & ~(7 << CW_PER_PAGE));
                nandc_set_reg(chip, NAND_DEV0_CFG1, host->cfg1_raw);
                instrs = 3;
-       } else {
+       } else if (q_op.cmd_reg != OP_RESET_DEVICE) {
                return 0;
        }
 
@@ -2830,9 +2830,8 @@ static int qcom_misc_cmd_type_exec(struct nand_chip *chip, const struct nand_sub
        nandc_set_reg(chip, NAND_EXEC_CMD, 1);
 
        write_reg_dma(nandc, NAND_FLASH_CMD, instrs, NAND_BAM_NEXT_SGL);
-       (q_op.cmd_reg == OP_BLOCK_ERASE) ? write_reg_dma(nandc, NAND_DEV0_CFG0,
-       2, NAND_BAM_NEXT_SGL) : read_reg_dma(nandc,
-       NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
+       if (q_op.cmd_reg == OP_BLOCK_ERASE)
+               write_reg_dma(nandc, NAND_DEV0_CFG0, 2, NAND_BAM_NEXT_SGL);
 
        write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
        read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
index c0d0bce0b5942d67a139091f08441983f30dc074..8090390edaf9dbb6832c6e30c25bb0ad1068e6cc 100644 (file)
@@ -1883,14 +1883,16 @@ mt7530_port_vlan_del(struct dsa_switch *ds, int port,
 
 static int mt753x_mirror_port_get(unsigned int id, u32 val)
 {
-       return (id == ID_MT7531) ? MT7531_MIRROR_PORT_GET(val) :
-                                  MIRROR_PORT(val);
+       return (id == ID_MT7531 || id == ID_MT7988) ?
+                      MT7531_MIRROR_PORT_GET(val) :
+                      MIRROR_PORT(val);
 }
 
 static int mt753x_mirror_port_set(unsigned int id, u32 val)
 {
-       return (id == ID_MT7531) ? MT7531_MIRROR_PORT_SET(val) :
-                                  MIRROR_PORT(val);
+       return (id == ID_MT7531 || id == ID_MT7988) ?
+                      MT7531_MIRROR_PORT_SET(val) :
+                      MIRROR_PORT(val);
 }
 
 static int mt753x_port_mirror_add(struct dsa_switch *ds, int port,
@@ -2480,6 +2482,9 @@ mt7530_setup(struct dsa_switch *ds)
                           PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
        }
 
+       /* Allow mirroring frames received on the local port (monitor port). */
+       mt7530_set(priv, MT753X_AGC, LOCAL_EN);
+
        /* Setup VLAN ID 0 for VLAN-unaware bridges */
        ret = mt7530_setup_vlan0(priv);
        if (ret)
@@ -2591,6 +2596,9 @@ mt7531_setup_common(struct dsa_switch *ds)
                           PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
        }
 
+       /* Allow mirroring frames received on the local port (monitor port). */
+       mt7530_set(priv, MT753X_AGC, LOCAL_EN);
+
        /* Flush the FDB table */
        ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL);
        if (ret < 0)
index 585db03c054878f85ba69e6546cfc885491d8f4e..a08053390b285e3f27d0bc08a3acba3effd17007 100644 (file)
@@ -32,6 +32,10 @@ enum mt753x_id {
 #define SYSC_REG_RSTCTRL               0x34
 #define  RESET_MCM                     BIT(2)
 
+/* Register for ARL global control */
+#define MT753X_AGC                     0xc
+#define  LOCAL_EN                      BIT(7)
+
 /* Registers to mac forward control for unknown frames */
 #define MT7530_MFC                     0x10
 #define  BC_FFP(x)                     (((x) & 0xff) << 24)
index c95787cb908673c6ab1b236e9c447952e5e8e452..14daf432f30b5c9f01502d4d2b44909930c8e75a 100644 (file)
@@ -566,13 +566,61 @@ static void mv88e6xxx_translate_cmode(u8 cmode, unsigned long *supported)
                phy_interface_set_rgmii(supported);
 }
 
-static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
-                                      struct phylink_config *config)
+static void
+mv88e6250_setup_supported_interfaces(struct mv88e6xxx_chip *chip, int port,
+                                    struct phylink_config *config)
 {
        unsigned long *supported = config->supported_interfaces;
+       int err;
+       u16 reg;
 
-       /* Translate the default cmode */
-       mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
+       if (err) {
+               dev_err(chip->dev, "p%d: failed to read port status\n", port);
+               return;
+       }
+
+       switch (reg & MV88E6250_PORT_STS_PORTMODE_MASK) {
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_HALF_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_100_HALF_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_FULL_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_100_FULL_PHY:
+               __set_bit(PHY_INTERFACE_MODE_REVMII, supported);
+               break;
+
+       case MV88E6250_PORT_STS_PORTMODE_MII_HALF:
+       case MV88E6250_PORT_STS_PORTMODE_MII_FULL:
+               __set_bit(PHY_INTERFACE_MODE_MII, supported);
+               break;
+
+       case MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_200_RMII_FULL_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_HALF_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL_PHY:
+               __set_bit(PHY_INTERFACE_MODE_REVRMII, supported);
+               break;
+
+       case MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL:
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL:
+               __set_bit(PHY_INTERFACE_MODE_RMII, supported);
+               break;
+
+       case MV88E6250_PORT_STS_PORTMODE_MII_100_RGMII:
+               __set_bit(PHY_INTERFACE_MODE_RGMII, supported);
+               break;
+
+       default:
+               dev_err(chip->dev,
+                       "p%d: invalid port mode in status register: %04x\n",
+                       port, reg);
+       }
+}
+
+static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
+                                      struct phylink_config *config)
+{
+       if (!mv88e6xxx_phy_is_internal(chip, port))
+               mv88e6250_setup_supported_interfaces(chip, port, config);
 
        config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100;
 }
@@ -5657,7 +5705,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6141,
                .family = MV88E6XXX_FAMILY_6341,
                .name = "Marvell 88E6141",
-               .num_databases = 4096,
+               .num_databases = 256,
                .num_macs = 2048,
                .num_ports = 6,
                .num_internal_phys = 5,
@@ -6116,7 +6164,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
                .family = MV88E6XXX_FAMILY_6341,
                .name = "Marvell 88E6341",
-               .num_databases = 4096,
+               .num_databases = 256,
                .num_macs = 2048,
                .num_internal_phys = 5,
                .num_ports = 6,
index 86deeb347cbc1d82526f362f719c57ac17039bf0..ddadeb9bfdaeed6978d85d55ccd2e52710971529 100644 (file)
 #define MV88E6250_PORT_STS_PORTMODE_PHY_100_HALF       0x0900
 #define MV88E6250_PORT_STS_PORTMODE_PHY_10_FULL                0x0a00
 #define MV88E6250_PORT_STS_PORTMODE_PHY_100_FULL       0x0b00
-#define MV88E6250_PORT_STS_PORTMODE_MII_10_HALF                0x0c00
-#define MV88E6250_PORT_STS_PORTMODE_MII_100_HALF       0x0d00
-#define MV88E6250_PORT_STS_PORTMODE_MII_10_FULL                0x0e00
-#define MV88E6250_PORT_STS_PORTMODE_MII_100_FULL       0x0f00
+/* - Modes with PHY suffix use output instead of input clock
+ * - Modes without RMII or RGMII use MII
+ * - Modes without speed do not have a fixed speed specified in the manual
+ *   ("DC to x MHz" - variable clock support?)
+ */
+#define MV88E6250_PORT_STS_PORTMODE_MII_DISABLED               0x0000
+#define MV88E6250_PORT_STS_PORTMODE_MII_100_RGMII              0x0100
+#define MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL_PHY 0x0200
+#define MV88E6250_PORT_STS_PORTMODE_MII_200_RMII_FULL_PHY      0x0400
+#define MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL     0x0600
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL       0x0700
+#define MV88E6250_PORT_STS_PORTMODE_MII_HALF                   0x0800
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_HALF_PHY   0x0900
+#define MV88E6250_PORT_STS_PORTMODE_MII_FULL                   0x0a00
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL_PHY   0x0b00
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_HALF_PHY            0x0c00
+#define MV88E6250_PORT_STS_PORTMODE_MII_100_HALF_PHY           0x0d00
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_FULL_PHY            0x0e00
+#define MV88E6250_PORT_STS_PORTMODE_MII_100_FULL_PHY           0x0f00
 #define MV88E6XXX_PORT_STS_LINK                        0x0800
 #define MV88E6XXX_PORT_STS_DUPLEX              0x0400
 #define MV88E6XXX_PORT_STS_SPEED_MASK          0x0300
index 72ea97c5d5d424482fe6812cef1a013158319a70..82768b0e90262b80b949b959b40151a0ddd0b6a9 100644 (file)
@@ -436,10 +436,8 @@ static void umac_init(struct bcmasp_intf *intf)
        umac_wl(intf, 0x800, UMC_RX_MAX_PKT_SZ);
 }
 
-static int bcmasp_tx_poll(struct napi_struct *napi, int budget)
+static int bcmasp_tx_reclaim(struct bcmasp_intf *intf)
 {
-       struct bcmasp_intf *intf =
-               container_of(napi, struct bcmasp_intf, tx_napi);
        struct bcmasp_intf_stats64 *stats = &intf->stats64;
        struct device *kdev = &intf->parent->pdev->dev;
        unsigned long read, released = 0;
@@ -482,10 +480,16 @@ static int bcmasp_tx_poll(struct napi_struct *napi, int budget)
                                                        DESC_RING_COUNT);
        }
 
-       /* Ensure all descriptors have been written to DRAM for the hardware
-        * to see updated contents.
-        */
-       wmb();
+       return released;
+}
+
+static int bcmasp_tx_poll(struct napi_struct *napi, int budget)
+{
+       struct bcmasp_intf *intf =
+               container_of(napi, struct bcmasp_intf, tx_napi);
+       int released = 0;
+
+       released = bcmasp_tx_reclaim(intf);
 
        napi_complete(&intf->tx_napi);
 
@@ -797,6 +801,7 @@ static void bcmasp_init_tx(struct bcmasp_intf *intf)
        intf->tx_spb_dma_read = intf->tx_spb_dma_addr;
        intf->tx_spb_index = 0;
        intf->tx_spb_clean_index = 0;
+       memset(intf->tx_cbs, 0, sizeof(struct bcmasp_tx_cb) * DESC_RING_COUNT);
 
        /* Make sure channels are disabled */
        tx_spb_ctrl_wl(intf, 0x0, TX_SPB_CTRL_ENABLE);
@@ -885,6 +890,8 @@ static void bcmasp_netif_deinit(struct net_device *dev)
        } while (timeout-- > 0);
        tx_spb_dma_wl(intf, 0x0, TX_SPB_DMA_FIFO_CTRL);
 
+       bcmasp_tx_reclaim(intf);
+
        umac_enable_set(intf, UMC_CMD_TX_EN, 0);
 
        phy_stop(dev->phydev);
index 3e4fb3c3e8342ad3dbf7aa32df03fc4ce57e3cad..1be6d14030bcffc0fd149b6be0af819964284a4e 100644 (file)
@@ -2009,12 +2009,14 @@ static int b44_set_pauseparam(struct net_device *dev,
                bp->flags |= B44_FLAG_TX_PAUSE;
        else
                bp->flags &= ~B44_FLAG_TX_PAUSE;
-       if (bp->flags & B44_FLAG_PAUSE_AUTO) {
-               b44_halt(bp);
-               b44_init_rings(bp);
-               b44_init_hw(bp, B44_FULL_RESET);
-       } else {
-               __b44_set_flow_ctrl(bp, bp->flags);
+       if (netif_running(dev)) {
+               if (bp->flags & B44_FLAG_PAUSE_AUTO) {
+                       b44_halt(bp);
+                       b44_init_rings(bp);
+                       b44_init_hw(bp, B44_FULL_RESET);
+               } else {
+                       __b44_set_flow_ctrl(bp, bp->flags);
+               }
        }
        spin_unlock_irq(&bp->lock);
 
index 57e61f9631678edf31a2ff237fe0301254a396e5..2c2ee79c4d77957761d8f3d9ca85bcecedd5fd0f 100644 (file)
@@ -1778,7 +1778,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                skb = bnxt_copy_skb(bnapi, data_ptr, len, mapping);
                if (!skb) {
                        bnxt_abort_tpa(cpr, idx, agg_bufs);
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
+                       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
        } else {
@@ -1788,7 +1788,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                new_data = __bnxt_alloc_rx_frag(bp, &new_mapping, GFP_ATOMIC);
                if (!new_data) {
                        bnxt_abort_tpa(cpr, idx, agg_bufs);
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
+                       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
 
@@ -1804,7 +1804,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                if (!skb) {
                        skb_free_frag(data);
                        bnxt_abort_tpa(cpr, idx, agg_bufs);
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
+                       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
                skb_reserve(skb, bp->rx_offset);
@@ -1815,7 +1815,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                skb = bnxt_rx_agg_pages_skb(bp, cpr, skb, idx, agg_bufs, true);
                if (!skb) {
                        /* Page reuse already handled by bnxt_rx_pages(). */
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
+                       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
        }
@@ -2094,11 +2094,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
                        u32 frag_len = bnxt_rx_agg_pages_xdp(bp, cpr, &xdp,
                                                             cp_cons, agg_bufs,
                                                             false);
-                       if (!frag_len) {
-                               cpr->sw_stats.rx.rx_oom_discards += 1;
-                               rc = -ENOMEM;
-                               goto next_rx;
-                       }
+                       if (!frag_len)
+                               goto oom_next_rx;
                }
                xdp_active = true;
        }
@@ -2121,9 +2118,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
                                else
                                        bnxt_xdp_buff_frags_free(rxr, &xdp);
                        }
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
-                       rc = -ENOMEM;
-                       goto next_rx;
+                       goto oom_next_rx;
                }
        } else {
                u32 payload;
@@ -2134,29 +2129,21 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
                        payload = 0;
                skb = bp->rx_skb_func(bp, rxr, cons, data, data_ptr, dma_addr,
                                      payload | len);
-               if (!skb) {
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
-                       rc = -ENOMEM;
-                       goto next_rx;
-               }
+               if (!skb)
+                       goto oom_next_rx;
        }
 
        if (agg_bufs) {
                if (!xdp_active) {
                        skb = bnxt_rx_agg_pages_skb(bp, cpr, skb, cp_cons, agg_bufs, false);
-                       if (!skb) {
-                               cpr->sw_stats.rx.rx_oom_discards += 1;
-                               rc = -ENOMEM;
-                               goto next_rx;
-                       }
+                       if (!skb)
+                               goto oom_next_rx;
                } else {
                        skb = bnxt_xdp_build_skb(bp, skb, agg_bufs, rxr->page_pool, &xdp, rxcmp1);
                        if (!skb) {
                                /* we should be able to free the old skb here */
                                bnxt_xdp_buff_frags_free(rxr, &xdp);
-                               cpr->sw_stats.rx.rx_oom_discards += 1;
-                               rc = -ENOMEM;
-                               goto next_rx;
+                               goto oom_next_rx;
                        }
                }
        }
@@ -2234,6 +2221,11 @@ next_rx_no_prod_no_len:
        *raw_cons = tmp_raw_cons;
 
        return rc;
+
+oom_next_rx:
+       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
+       rc = -ENOMEM;
+       goto next_rx;
 }
 
 /* In netpoll mode, if we are using a combined completion ring, we need to
@@ -2280,7 +2272,7 @@ static int bnxt_force_rx_discard(struct bnxt *bp,
        }
        rc = bnxt_rx_pkt(bp, cpr, raw_cons, event);
        if (rc && rc != -EBUSY)
-               cpr->sw_stats.rx.rx_netpoll_discards += 1;
+               cpr->bnapi->cp_ring.sw_stats.rx.rx_netpoll_discards += 1;
        return rc;
 }
 
@@ -9089,7 +9081,7 @@ static void bnxt_try_map_fw_health_reg(struct bnxt *bp)
                                             BNXT_FW_HEALTH_WIN_BASE +
                                             BNXT_GRC_REG_CHIP_NUM);
                }
-               if (!BNXT_CHIP_P5(bp))
+               if (!BNXT_CHIP_P5_PLUS(bp))
                        return;
 
                status_loc = BNXT_GRC_REG_STATUS_P5 |
@@ -13037,6 +13029,16 @@ static void bnxt_rx_ring_reset(struct bnxt *bp)
        bnxt_rtnl_unlock_sp(bp);
 }
 
+static void bnxt_fw_fatal_close(struct bnxt *bp)
+{
+       bnxt_tx_disable(bp);
+       bnxt_disable_napi(bp);
+       bnxt_disable_int_sync(bp);
+       bnxt_free_irq(bp);
+       bnxt_clear_int_mode(bp);
+       pci_disable_device(bp->pdev);
+}
+
 static void bnxt_fw_reset_close(struct bnxt *bp)
 {
        bnxt_ulp_stop(bp);
@@ -13050,12 +13052,7 @@ static void bnxt_fw_reset_close(struct bnxt *bp)
                pci_read_config_word(bp->pdev, PCI_SUBSYSTEM_ID, &val);
                if (val == 0xffff)
                        bp->fw_reset_min_dsecs = 0;
-               bnxt_tx_disable(bp);
-               bnxt_disable_napi(bp);
-               bnxt_disable_int_sync(bp);
-               bnxt_free_irq(bp);
-               bnxt_clear_int_mode(bp);
-               pci_disable_device(bp->pdev);
+               bnxt_fw_fatal_close(bp);
        }
        __bnxt_close_nic(bp, true, false);
        bnxt_vf_reps_free(bp);
@@ -15373,6 +15370,7 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct bnxt *bp = netdev_priv(netdev);
+       bool abort = false;
 
        netdev_info(netdev, "PCI I/O error detected\n");
 
@@ -15381,16 +15379,27 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
 
        bnxt_ulp_stop(bp);
 
-       if (state == pci_channel_io_perm_failure) {
+       if (test_and_set_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
+               netdev_err(bp->dev, "Firmware reset already in progress\n");
+               abort = true;
+       }
+
+       if (abort || state == pci_channel_io_perm_failure) {
                rtnl_unlock();
                return PCI_ERS_RESULT_DISCONNECT;
        }
 
-       if (state == pci_channel_io_frozen)
+       /* Link is not reliable anymore if state is pci_channel_io_frozen
+        * so we disable bus master to prevent any potential bad DMAs before
+        * freeing kernel memory.
+        */
+       if (state == pci_channel_io_frozen) {
                set_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN, &bp->state);
+               bnxt_fw_fatal_close(bp);
+       }
 
        if (netif_running(netdev))
-               bnxt_close(netdev);
+               __bnxt_close_nic(bp, true, true);
 
        if (pci_is_enabled(pdev))
                pci_disable_device(pdev);
@@ -15474,6 +15483,7 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
        }
 
 reset_exit:
+       clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
        bnxt_clear_reservations(bp, true);
        rtnl_unlock();
 
index b1f84b37032a7833d7e4f3d045e8755ace6f79d3..c7e7dac057a336d086bdf9569286fadec7e1d3be 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Broadcom GENET (Gigabit Ethernet) controller driver
  *
- * Copyright (c) 2014-2020 Broadcom
+ * Copyright (c) 2014-2024 Broadcom
  */
 
 #define pr_fmt(fmt)                            "bcmgenet: " fmt
@@ -2467,14 +2467,18 @@ static void umac_enable_set(struct bcmgenet_priv *priv, u32 mask, bool enable)
 {
        u32 reg;
 
+       spin_lock_bh(&priv->reg_lock);
        reg = bcmgenet_umac_readl(priv, UMAC_CMD);
-       if (reg & CMD_SW_RESET)
+       if (reg & CMD_SW_RESET) {
+               spin_unlock_bh(&priv->reg_lock);
                return;
+       }
        if (enable)
                reg |= mask;
        else
                reg &= ~mask;
        bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+       spin_unlock_bh(&priv->reg_lock);
 
        /* UniMAC stops on a packet boundary, wait for a full-size packet
         * to be processed
@@ -2490,8 +2494,10 @@ static void reset_umac(struct bcmgenet_priv *priv)
        udelay(10);
 
        /* issue soft reset and disable MAC while updating its registers */
+       spin_lock_bh(&priv->reg_lock);
        bcmgenet_umac_writel(priv, CMD_SW_RESET, UMAC_CMD);
        udelay(2);
+       spin_unlock_bh(&priv->reg_lock);
 }
 
 static void bcmgenet_intr_disable(struct bcmgenet_priv *priv)
@@ -3334,7 +3340,9 @@ static void bcmgenet_netif_start(struct net_device *dev)
        struct bcmgenet_priv *priv = netdev_priv(dev);
 
        /* Start the network engine */
+       netif_addr_lock_bh(dev);
        bcmgenet_set_rx_mode(dev);
+       netif_addr_unlock_bh(dev);
        bcmgenet_enable_rx_napi(priv);
 
        umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true);
@@ -3595,16 +3603,19 @@ static void bcmgenet_set_rx_mode(struct net_device *dev)
         * 3. The number of filters needed exceeds the number filters
         *    supported by the hardware.
        */
+       spin_lock(&priv->reg_lock);
        reg = bcmgenet_umac_readl(priv, UMAC_CMD);
        if ((dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) ||
            (nfilter > MAX_MDF_FILTER)) {
                reg |= CMD_PROMISC;
                bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+               spin_unlock(&priv->reg_lock);
                bcmgenet_umac_writel(priv, 0, UMAC_MDF_CTRL);
                return;
        } else {
                reg &= ~CMD_PROMISC;
                bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+               spin_unlock(&priv->reg_lock);
        }
 
        /* update MDF filter */
@@ -4003,6 +4014,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
                goto err;
        }
 
+       spin_lock_init(&priv->reg_lock);
        spin_lock_init(&priv->lock);
 
        /* Set default pause parameters */
index 7523b60b3c1c016de74fd74b7d1e286596aac1ae..43b923c48b14f40e0cf9cdd6b6f3ac16c301ef97 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2014-2020 Broadcom
+ * Copyright (c) 2014-2024 Broadcom
  */
 
 #ifndef __BCMGENET_H__
@@ -573,6 +573,8 @@ struct bcmgenet_rxnfc_rule {
 /* device context */
 struct bcmgenet_priv {
        void __iomem *base;
+       /* reg_lock: lock to serialize access to shared registers */
+       spinlock_t reg_lock;
        enum bcmgenet_version version;
        struct net_device *dev;
 
index 7a41cad5788f4edd6691552901f4b2eb8fdebc36..1248792d7fd4d2f98847889c499277a92229d785 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Broadcom GENET (Gigabit Ethernet) Wake-on-LAN support
  *
- * Copyright (c) 2014-2020 Broadcom
+ * Copyright (c) 2014-2024 Broadcom
  */
 
 #define pr_fmt(fmt)                            "bcmgenet_wol: " fmt
@@ -151,6 +151,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
        }
 
        /* Can't suspend with WoL if MAC is still in reset */
+       spin_lock_bh(&priv->reg_lock);
        reg = bcmgenet_umac_readl(priv, UMAC_CMD);
        if (reg & CMD_SW_RESET)
                reg &= ~CMD_SW_RESET;
@@ -158,6 +159,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
        /* disable RX */
        reg &= ~CMD_RX_EN;
        bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+       spin_unlock_bh(&priv->reg_lock);
        mdelay(10);
 
        if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
@@ -203,6 +205,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
        }
 
        /* Enable CRC forward */
+       spin_lock_bh(&priv->reg_lock);
        reg = bcmgenet_umac_readl(priv, UMAC_CMD);
        priv->crc_fwd_en = 1;
        reg |= CMD_CRC_FWD;
@@ -210,6 +213,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
        /* Receiver must be enabled for WOL MP detection */
        reg |= CMD_RX_EN;
        bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+       spin_unlock_bh(&priv->reg_lock);
 
        reg = UMAC_IRQ_MPD_R;
        if (hfb_enable)
@@ -256,7 +260,9 @@ void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
        }
 
        /* Disable CRC Forward */
+       spin_lock_bh(&priv->reg_lock);
        reg = bcmgenet_umac_readl(priv, UMAC_CMD);
        reg &= ~CMD_CRC_FWD;
        bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+       spin_unlock_bh(&priv->reg_lock);
 }
index 9ada89355747554dc458c311f96333866cf7bc66..c4a3698cef66f61d775c783b334a035589d55bdd 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Broadcom GENET MDIO routines
  *
- * Copyright (c) 2014-2017 Broadcom
+ * Copyright (c) 2014-2024 Broadcom
  */
 
 #include <linux/acpi.h>
@@ -76,6 +76,7 @@ static void bcmgenet_mac_config(struct net_device *dev)
        reg |= RGMII_LINK;
        bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
 
+       spin_lock_bh(&priv->reg_lock);
        reg = bcmgenet_umac_readl(priv, UMAC_CMD);
        reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
                       CMD_HD_EN |
@@ -88,6 +89,7 @@ static void bcmgenet_mac_config(struct net_device *dev)
                reg |= CMD_TX_EN | CMD_RX_EN;
        }
        bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+       spin_unlock_bh(&priv->reg_lock);
 
        active = phy_init_eee(phydev, 0) >= 0;
        bcmgenet_eee_enable_set(dev,
@@ -275,6 +277,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
         * block for the interface to work, unconditionally clear the
         * Out-of-band disable since we do not need it.
         */
+       mutex_lock(&phydev->lock);
        reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
        reg &= ~OOB_DISABLE;
        if (priv->ext_phy) {
@@ -286,6 +289,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
                        reg |= RGMII_MODE_EN;
        }
        bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
+       mutex_unlock(&phydev->lock);
 
        if (init)
                dev_info(kdev, "configuring instance for %s\n", phy_name);
index 7246e13dd559fc37170c791644cf5a8fd8d04fcf..97291bfbeea589e8ca8ab637db8bcff7e573322f 100644 (file)
@@ -312,7 +312,7 @@ bnad_debugfs_write_regrd(struct file *file, const char __user *buf,
        void *kern_buf;
 
        /* Copy the user space buf */
-       kern_buf = memdup_user(buf, nbytes);
+       kern_buf = memdup_user_nul(buf, nbytes);
        if (IS_ERR(kern_buf))
                return PTR_ERR(kern_buf);
 
@@ -372,7 +372,7 @@ bnad_debugfs_write_regwr(struct file *file, const char __user *buf,
        void *kern_buf;
 
        /* Copy the user space buf */
-       kern_buf = memdup_user(buf, nbytes);
+       kern_buf = memdup_user_nul(buf, nbytes);
        if (IS_ERR(kern_buf))
                return PTR_ERR(kern_buf);
 
index 49d5808b7d11d281796debc6be5f9b3a9b1f60e3..de52bcb884c417098ff5aff6aea77753d055c671 100644 (file)
@@ -2670,12 +2670,12 @@ int cxgb4_selftest_lb_pkt(struct net_device *netdev)
        lb->loopback = 1;
 
        q = &adap->sge.ethtxq[pi->first_qset];
-       __netif_tx_lock(q->txq, smp_processor_id());
+       __netif_tx_lock_bh(q->txq);
 
        reclaim_completed_tx(adap, &q->q, -1, true);
        credits = txq_avail(&q->q) - ndesc;
        if (unlikely(credits < 0)) {
-               __netif_tx_unlock(q->txq);
+               __netif_tx_unlock_bh(q->txq);
                return -ENOMEM;
        }
 
@@ -2710,7 +2710,7 @@ int cxgb4_selftest_lb_pkt(struct net_device *netdev)
        init_completion(&lb->completion);
        txq_advance(&q->q, ndesc);
        cxgb4_ring_tx_db(adap, &q->q, ndesc);
-       __netif_tx_unlock(q->txq);
+       __netif_tx_unlock_bh(q->txq);
 
        /* wait for the pkt to return */
        ret = wait_for_completion_timeout(&lb->completion, 10 * HZ);
index 93544f1cc2a51be0c84c33391211bf47d2675edb..f7ae0e0aa4a4f52d7ff720c11fb906cac00f7c5a 100644 (file)
@@ -157,7 +157,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
                 * the lower time out
                 */
                for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
-                       usleep_range(50, 60);
+                       udelay(50);
                        mdic = er32(MDIC);
                        if (mdic & E1000_MDIC_READY)
                                break;
@@ -181,7 +181,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
                 * reading duplicate data in the next MDIC transaction.
                 */
                if (hw->mac.type == e1000_pch2lan)
-                       usleep_range(100, 150);
+                       udelay(100);
 
                if (success) {
                        *data = (u16)mdic;
@@ -237,7 +237,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
                 * the lower time out
                 */
                for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
-                       usleep_range(50, 60);
+                       udelay(50);
                        mdic = er32(MDIC);
                        if (mdic & E1000_MDIC_READY)
                                break;
@@ -261,7 +261,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
                 * reading duplicate data in the next MDIC transaction.
                 */
                if (hw->mac.type == e1000_pch2lan)
-                       usleep_range(100, 150);
+                       udelay(100);
 
                if (success)
                        return 0;
index 48b9ddb2b1b38b385527f137124ce86a36ac036d..ffb9f9f15c5232e2aeb4a45c1209b6a0763062d7 100644 (file)
@@ -16107,8 +16107,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        val = FIELD_GET(I40E_PRTGL_SAH_MFS_MASK,
                        rd32(&pf->hw, I40E_PRTGL_SAH));
        if (val < MAX_FRAME_SIZE_DEFAULT)
-               dev_warn(&pdev->dev, "MFS for port %x has been set below the default: %x\n",
-                        pf->hw.port, val);
+               dev_warn(&pdev->dev, "MFS for port %x (%d) has been set below the default (%d)\n",
+                        pf->hw.port, val, MAX_FRAME_SIZE_DEFAULT);
 
        /* Add a filter to drop all Flow control frames from any VSI from being
         * transmitted. By doing so we stop a malicious VF from sending out
@@ -16650,7 +16650,7 @@ static int __init i40e_init_module(void)
         * since we need to be able to guarantee forward progress even under
         * memory pressure.
         */
-       i40e_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, i40e_driver_name);
+       i40e_wq = alloc_workqueue("%s", 0, 0, i40e_driver_name);
        if (!i40e_wq) {
                pr_err("%s: Failed to create workqueue\n", i40e_driver_name);
                return -ENOMEM;
index ef2440f3abf8b6aed9f47e5948f67a5dec52b51e..166832a4213a289f17198d748f4abea1d5e4efc4 100644 (file)
@@ -3502,6 +3502,34 @@ static void iavf_del_all_cloud_filters(struct iavf_adapter *adapter)
        spin_unlock_bh(&adapter->cloud_filter_list_lock);
 }
 
+/**
+ * iavf_is_tc_config_same - Compare the mqprio TC config with the
+ * TC config already configured on this adapter.
+ * @adapter: board private structure
+ * @mqprio_qopt: TC config received from kernel.
+ *
+ * This function compares the TC config received from the kernel
+ * with the config already configured on the adapter.
+ *
+ * Return: True if configuration is same, false otherwise.
+ **/
+static bool iavf_is_tc_config_same(struct iavf_adapter *adapter,
+                                  struct tc_mqprio_qopt *mqprio_qopt)
+{
+       struct virtchnl_channel_info *ch = &adapter->ch_config.ch_info[0];
+       int i;
+
+       if (adapter->num_tc != mqprio_qopt->num_tc)
+               return false;
+
+       for (i = 0; i < adapter->num_tc; i++) {
+               if (ch[i].count != mqprio_qopt->count[i] ||
+                   ch[i].offset != mqprio_qopt->offset[i])
+                       return false;
+       }
+       return true;
+}
+
 /**
  * __iavf_setup_tc - configure multiple traffic classes
  * @netdev: network interface device structure
@@ -3559,7 +3587,7 @@ static int __iavf_setup_tc(struct net_device *netdev, void *type_data)
                if (ret)
                        return ret;
                /* Return if same TC config is requested */
-               if (adapter->num_tc == num_tc)
+               if (iavf_is_tc_config_same(adapter, &mqprio_qopt->qopt))
                        return 0;
                adapter->num_tc = num_tc;
 
index d252d98218d084e9782d899d4f854c0bf7101622..9fc0fd95a13d8f2c40475a94f38d3a2c088ab6f4 100644 (file)
@@ -171,7 +171,7 @@ ice_debugfs_module_write(struct file *filp, const char __user *buf,
        if (*ppos != 0 || count > 8)
                return -EINVAL;
 
-       cmd_buf = memdup_user(buf, count);
+       cmd_buf = memdup_user_nul(buf, count);
        if (IS_ERR(cmd_buf))
                return PTR_ERR(cmd_buf);
 
@@ -257,7 +257,7 @@ ice_debugfs_nr_messages_write(struct file *filp, const char __user *buf,
        if (*ppos != 0 || count > 4)
                return -EINVAL;
 
-       cmd_buf = memdup_user(buf, count);
+       cmd_buf = memdup_user_nul(buf, count);
        if (IS_ERR(cmd_buf))
                return PTR_ERR(cmd_buf);
 
@@ -332,7 +332,7 @@ ice_debugfs_enable_write(struct file *filp, const char __user *buf,
        if (*ppos != 0 || count > 2)
                return -EINVAL;
 
-       cmd_buf = memdup_user(buf, count);
+       cmd_buf = memdup_user_nul(buf, count);
        if (IS_ERR(cmd_buf))
                return PTR_ERR(cmd_buf);
 
@@ -428,7 +428,7 @@ ice_debugfs_log_size_write(struct file *filp, const char __user *buf,
        if (*ppos != 0 || count > 5)
                return -EINVAL;
 
-       cmd_buf = memdup_user(buf, count);
+       cmd_buf = memdup_user_nul(buf, count);
        if (IS_ERR(cmd_buf))
                return PTR_ERR(cmd_buf);
 
index b890410a2bc0bacd27eab5acd6f87cd8b0110939..688ccb0615ab9f87e7caf9e6fa522444613b2bf3 100644 (file)
@@ -28,6 +28,8 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
         * - ICE_TC_FLWR_FIELD_VLAN_TPID (present if specified)
         * - Tunnel flag (present if tunnel)
         */
+       if (fltr->direction == ICE_ESWITCH_FLTR_EGRESS)
+               lkups_cnt++;
 
        if (flags & ICE_TC_FLWR_FIELD_TENANT_ID)
                lkups_cnt++;
@@ -363,6 +365,11 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
        /* Always add direction metadata */
        ice_rule_add_direction_metadata(&list[ICE_TC_METADATA_LKUP_IDX]);
 
+       if (tc_fltr->direction == ICE_ESWITCH_FLTR_EGRESS) {
+               ice_rule_add_src_vsi_metadata(&list[i]);
+               i++;
+       }
+
        rule_info->tun_type = ice_sw_type_from_tunnel(tc_fltr->tunnel_type);
        if (tc_fltr->tunnel_type != TNL_LAST) {
                i = ice_tc_fill_tunnel_outer(flags, tc_fltr, list, i);
@@ -772,7 +779,7 @@ ice_eswitch_add_tc_fltr(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr)
        int ret;
        int i;
 
-       if (!flags || (flags & ICE_TC_FLWR_FIELD_ENC_SRC_L4_PORT)) {
+       if (flags & ICE_TC_FLWR_FIELD_ENC_SRC_L4_PORT) {
                NL_SET_ERR_MSG_MOD(fltr->extack, "Unsupported encap field(s)");
                return -EOPNOTSUPP;
        }
@@ -820,6 +827,7 @@ ice_eswitch_add_tc_fltr(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr)
 
        /* specify the cookie as filter_rule_id */
        rule_info.fltr_rule_id = fltr->cookie;
+       rule_info.src_vsi = vsi->idx;
 
        ret = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info, &rule_added);
        if (ret == -EEXIST) {
@@ -1481,7 +1489,10 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
                  (BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
                   BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
                   BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID) |
-                  BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS))) {
+                  BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS) |
+                  BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IP) |
+                  BIT_ULL(FLOW_DISSECTOR_KEY_ENC_OPTS) |
+                  BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL))) {
                NL_SET_ERR_MSG_MOD(fltr->extack, "Tunnel key used, but device isn't a tunnel");
                return -EOPNOTSUPP;
        } else {
index 21d26e19338a69acb265a279bfc633bbfea0cad2..d10a4be965b591027c357be2c5ede2ab3269a7da 100644 (file)
@@ -856,6 +856,11 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
                return 0;
        }
 
+       if (flags & ICE_VF_RESET_LOCK)
+               mutex_lock(&vf->cfg_lock);
+       else
+               lockdep_assert_held(&vf->cfg_lock);
+
        lag = pf->lag;
        mutex_lock(&pf->lag_mutex);
        if (lag && lag->bonded && lag->primary) {
@@ -867,11 +872,6 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
                        act_prt = ICE_LAG_INVALID_PORT;
        }
 
-       if (flags & ICE_VF_RESET_LOCK)
-               mutex_lock(&vf->cfg_lock);
-       else
-               lockdep_assert_held(&vf->cfg_lock);
-
        if (ice_is_vf_disabled(vf)) {
                vsi = ice_get_vf_vsi(vf);
                if (!vsi) {
@@ -956,14 +956,14 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
        ice_mbx_clear_malvf(&vf->mbx_info);
 
 out_unlock:
-       if (flags & ICE_VF_RESET_LOCK)
-               mutex_unlock(&vf->cfg_lock);
-
        if (lag && lag->bonded && lag->primary &&
            act_prt != ICE_LAG_INVALID_PORT)
                ice_lag_move_vf_nodes_cfg(lag, pri_prt, act_prt);
        mutex_unlock(&pf->lag_mutex);
 
+       if (flags & ICE_VF_RESET_LOCK)
+               mutex_unlock(&vf->cfg_lock);
+
        return err;
 }
 
index 90316dc58630874d98aeb4095dc991c259a593f4..6bc56c7c181e4882d3ec99ea86e01c8188682175 100644 (file)
@@ -298,6 +298,7 @@ struct igc_adapter {
 
        /* LEDs */
        struct mutex led_mutex;
+       struct igc_led_classdev *leds;
 };
 
 void igc_up(struct igc_adapter *adapter);
@@ -723,6 +724,7 @@ void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts);
 void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter);
 
 int igc_led_setup(struct igc_adapter *adapter);
+void igc_led_free(struct igc_adapter *adapter);
 
 #define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
 
index bf240c5daf8657b3f9dd89f58fda05f87e57e5ae..3929b25b6ae6eb55335a5a6eb7b6494c4cc21982 100644 (file)
@@ -236,8 +236,8 @@ static void igc_led_get_name(struct igc_adapter *adapter, int index, char *buf,
                 pci_dev_id(adapter->pdev), index);
 }
 
-static void igc_setup_ldev(struct igc_led_classdev *ldev,
-                          struct net_device *netdev, int index)
+static int igc_setup_ldev(struct igc_led_classdev *ldev,
+                         struct net_device *netdev, int index)
 {
        struct igc_adapter *adapter = netdev_priv(netdev);
        struct led_classdev *led_cdev = &ldev->led;
@@ -257,24 +257,46 @@ static void igc_setup_ldev(struct igc_led_classdev *ldev,
        led_cdev->hw_control_get = igc_led_hw_control_get;
        led_cdev->hw_control_get_device = igc_led_hw_control_get_device;
 
-       devm_led_classdev_register(&netdev->dev, led_cdev);
+       return led_classdev_register(&netdev->dev, led_cdev);
 }
 
 int igc_led_setup(struct igc_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
-       struct device *dev = &netdev->dev;
        struct igc_led_classdev *leds;
-       int i;
+       int i, err;
 
        mutex_init(&adapter->led_mutex);
 
-       leds = devm_kcalloc(dev, IGC_NUM_LEDS, sizeof(*leds), GFP_KERNEL);
+       leds = kcalloc(IGC_NUM_LEDS, sizeof(*leds), GFP_KERNEL);
        if (!leds)
                return -ENOMEM;
 
-       for (i = 0; i < IGC_NUM_LEDS; i++)
-               igc_setup_ldev(leds + i, netdev, i);
+       for (i = 0; i < IGC_NUM_LEDS; i++) {
+               err = igc_setup_ldev(leds + i, netdev, i);
+               if (err)
+                       goto err;
+       }
+
+       adapter->leds = leds;
 
        return 0;
+
+err:
+       for (i--; i >= 0; i--)
+               led_classdev_unregister(&((leds + i)->led));
+
+       kfree(leds);
+       return err;
+}
+
+void igc_led_free(struct igc_adapter *adapter)
+{
+       struct igc_led_classdev *leds = adapter->leds;
+       int i;
+
+       for (i = 0; i < IGC_NUM_LEDS; i++)
+               led_classdev_unregister(&((leds + i)->led));
+
+       kfree(leds);
 }
index 35ad40a803cb64a66b983b3a2103a8f15b808df5..4d975d620a8e4b925fe3798a792f2a365877c5a8 100644 (file)
@@ -7021,6 +7021,9 @@ static void igc_remove(struct pci_dev *pdev)
        cancel_work_sync(&adapter->watchdog_task);
        hrtimer_cancel(&adapter->hrtimer);
 
+       if (IS_ENABLED(CONFIG_IGC_LEDS))
+               igc_led_free(adapter);
+
        /* Release control of h/w to f/w.  If f/w is AMT enabled, this
         * would have already happened in close and is redundant.
         */
index 2500f5ba4f5a42b43ee5de8d64d7f06fb70cdd87..881d704644fbee77cf5c9f7137d539463c08c2dd 100644 (file)
@@ -999,12 +999,10 @@ static ssize_t rvu_dbg_qsize_write(struct file *filp,
        u16 pcifunc;
        int ret, lf;
 
-       cmd_buf = memdup_user(buffer, count + 1);
+       cmd_buf = memdup_user_nul(buffer, count);
        if (IS_ERR(cmd_buf))
                return -ENOMEM;
 
-       cmd_buf[count] = '\0';
-
        cmd_buf_tmp = strchr(cmd_buf, '\n');
        if (cmd_buf_tmp) {
                *cmd_buf_tmp = '\0';
index be709f83f3318cd8766ca6a2e6b51b88fa8a30e3..e8b73b9d75e3118f56ee42a322d05491b0c325f0 100644 (file)
@@ -2181,7 +2181,6 @@ void rvu_npc_freemem(struct rvu *rvu)
 
        kfree(pkind->rsrc.bmap);
        npc_mcam_rsrcs_deinit(rvu);
-       kfree(mcam->counters.bmap);
        if (rvu->kpu_prfl_addr)
                iounmap(rvu->kpu_prfl_addr);
        else
index 87bdb93cb066e9afba84e5a93556c1efa0d780d9..f4655a8c0705d70b3a4aff580ccb1e437069ca64 100644 (file)
@@ -689,6 +689,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
 
        if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
                struct flow_match_control match;
+               u32 val;
 
                flow_rule_match_control(rule, &match);
                if (match.mask->flags & FLOW_DIS_FIRST_FRAG) {
@@ -697,12 +698,14 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
                }
 
                if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) {
+                       val = match.key->flags & FLOW_DIS_IS_FRAGMENT;
                        if (ntohs(flow_spec->etype) == ETH_P_IP) {
-                               flow_spec->ip_flag = IPV4_FLAG_MORE;
+                               flow_spec->ip_flag = val ? IPV4_FLAG_MORE : 0;
                                flow_mask->ip_flag = IPV4_FLAG_MORE;
                                req->features |= BIT_ULL(NPC_IPFRAG_IPV4);
                        } else if (ntohs(flow_spec->etype) == ETH_P_IPV6) {
-                               flow_spec->next_header = IPPROTO_FRAGMENT;
+                               flow_spec->next_header = val ?
+                                                        IPPROTO_FRAGMENT : 0;
                                flow_mask->next_header = 0xff;
                                req->features |= BIT_ULL(NPC_IPFRAG_IPV6);
                        } else {
index c895e265ae0ebcde930acf3785ba9ab1b63b65e5..61334a71058c7594a61ca768ce041f92ab238d24 100644 (file)
@@ -1074,13 +1074,13 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
 static void
 mtk_wed_stop(struct mtk_wed_device *dev)
 {
+       mtk_wed_dma_disable(dev);
        mtk_wed_set_ext_int(dev, false);
 
        wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0);
        wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0);
        wdma_w32(dev, MTK_WDMA_INT_MASK, 0);
        wdma_w32(dev, MTK_WDMA_INT_GRP2, 0);
-       wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0);
 
        if (!mtk_wed_get_rx_capa(dev))
                return;
@@ -1093,7 +1093,6 @@ static void
 mtk_wed_deinit(struct mtk_wed_device *dev)
 {
        mtk_wed_stop(dev);
-       mtk_wed_dma_disable(dev);
 
        wed_clr(dev, MTK_WED_CTRL,
                MTK_WED_CTRL_WDMA_INT_AGENT_EN |
@@ -2605,9 +2604,6 @@ mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
 static void
 mtk_wed_irq_set_mask(struct mtk_wed_device *dev, u32 mask)
 {
-       if (!dev->running)
-               return;
-
        mtk_wed_set_ext_int(dev, !!mask);
        wed_w32(dev, MTK_WED_INT_MASK, mask);
 }
index 0ab9db319530258fab6c7e6ad5648e13550069f8..22918b2ef7f128849be838063819ed12509abb45 100644 (file)
@@ -108,7 +108,10 @@ static int mlx5e_tx_reporter_err_cqe_recover(void *ctx)
        mlx5e_reset_txqsq_cc_pc(sq);
        sq->stats->recover++;
        clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
+       rtnl_lock();
        mlx5e_activate_txqsq(sq);
+       rtnl_unlock();
+
        if (sq->channel)
                mlx5e_trigger_napi_icosq(sq->channel);
        else
@@ -179,12 +182,16 @@ static int mlx5e_tx_reporter_ptpsq_unhealthy_recover(void *ctx)
        carrier_ok = netif_carrier_ok(netdev);
        netif_carrier_off(netdev);
 
+       rtnl_lock();
        mlx5e_deactivate_priv_channels(priv);
+       rtnl_unlock();
 
        mlx5e_ptp_close(chs->ptp);
        err = mlx5e_ptp_open(priv, &chs->params, chs->c[0]->lag_port, &chs->ptp);
 
+       rtnl_lock();
        mlx5e_activate_priv_channels(priv);
+       rtnl_unlock();
 
        /* return carrier back if needed */
        if (carrier_ok)
index b2cabd6ab86cb9044f8d0dc404fa8a052d31938c..cc9bcc420032428eee5188e692991d50aaffc684 100644 (file)
@@ -1640,6 +1640,7 @@ static const struct macsec_ops macsec_offload_ops = {
        .mdo_add_secy = mlx5e_macsec_add_secy,
        .mdo_upd_secy = mlx5e_macsec_upd_secy,
        .mdo_del_secy = mlx5e_macsec_del_secy,
+       .rx_uses_md_dst = true,
 };
 
 bool mlx5e_macsec_handle_tx_skb(struct mlx5e_macsec *macsec, struct sk_buff *skb)
index c7f542d0b8f08c635a6fad868a364a8f5f91ba8c..93cf23278d93c2629977f38ee7a39e7cd6c0aaa6 100644 (file)
@@ -46,6 +46,10 @@ struct arfs_table {
        struct hlist_head        rules_hash[ARFS_HASH_SIZE];
 };
 
+enum {
+       MLX5E_ARFS_STATE_ENABLED,
+};
+
 enum arfs_type {
        ARFS_IPV4_TCP,
        ARFS_IPV6_TCP,
@@ -60,6 +64,7 @@ struct mlx5e_arfs_tables {
        spinlock_t                     arfs_lock;
        int                            last_filter_id;
        struct workqueue_struct        *wq;
+       unsigned long                  state;
 };
 
 struct arfs_tuple {
@@ -170,6 +175,8 @@ int mlx5e_arfs_enable(struct mlx5e_flow_steering *fs)
                        return err;
                }
        }
+       set_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state);
+
        return 0;
 }
 
@@ -455,6 +462,8 @@ static void arfs_del_rules(struct mlx5e_flow_steering *fs)
        int i;
        int j;
 
+       clear_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state);
+
        spin_lock_bh(&arfs->arfs_lock);
        mlx5e_for_each_arfs_rule(rule, htmp, arfs->arfs_tables, i, j) {
                hlist_del_init(&rule->hlist);
@@ -627,17 +636,8 @@ static void arfs_handle_work(struct work_struct *work)
        struct mlx5_flow_handle *rule;
 
        arfs = mlx5e_fs_get_arfs(priv->fs);
-       mutex_lock(&priv->state_lock);
-       if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
-               spin_lock_bh(&arfs->arfs_lock);
-               hlist_del(&arfs_rule->hlist);
-               spin_unlock_bh(&arfs->arfs_lock);
-
-               mutex_unlock(&priv->state_lock);
-               kfree(arfs_rule);
-               goto out;
-       }
-       mutex_unlock(&priv->state_lock);
+       if (!test_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state))
+               return;
 
        if (!arfs_rule->rule) {
                rule = arfs_add_rule(priv, arfs_rule);
@@ -753,6 +753,11 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
                return -EPROTONOSUPPORT;
 
        spin_lock_bh(&arfs->arfs_lock);
+       if (!test_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state)) {
+               spin_unlock_bh(&arfs->arfs_lock);
+               return -EPERM;
+       }
+
        arfs_rule = arfs_find_rule(arfs_t, &fk);
        if (arfs_rule) {
                if (arfs_rule->rxq == rxq_index || work_busy(&arfs_rule->arfs_work)) {
index 8f101181648c6a294332b6229946b1afae4ee554..67a29826bb5702b8fd5e81e8673da5b6291bf7f3 100644 (file)
@@ -589,12 +589,12 @@ static int mlx5e_get_coalesce(struct net_device *netdev,
 static void
 mlx5e_set_priv_channels_tx_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal)
 {
-       struct mlx5_core_dev *mdev = priv->mdev;
        int tc;
        int i;
 
        for (i = 0; i < priv->channels.num; ++i) {
                struct mlx5e_channel *c = priv->channels.c[i];
+               struct mlx5_core_dev *mdev = c->mdev;
 
                for (tc = 0; tc < c->num_tc; tc++) {
                        mlx5_core_modify_cq_moderation(mdev,
@@ -608,11 +608,11 @@ mlx5e_set_priv_channels_tx_coalesce(struct mlx5e_priv *priv, struct ethtool_coal
 static void
 mlx5e_set_priv_channels_rx_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal)
 {
-       struct mlx5_core_dev *mdev = priv->mdev;
        int i;
 
        for (i = 0; i < priv->channels.num; ++i) {
                struct mlx5e_channel *c = priv->channels.c[i];
+               struct mlx5_core_dev *mdev = c->mdev;
 
                mlx5_core_modify_cq_moderation(mdev, &c->rq.cq.mcq,
                                               coal->rx_coalesce_usecs,
index b375ef268671ab01215e370149d1a3b9cb86b756..319930c04093ba2d15d498006ad9b3d060a883b7 100644 (file)
@@ -209,8 +209,8 @@ static int mlx5e_devcom_init_mpv(struct mlx5e_priv *priv, u64 *data)
                                                      *data,
                                                      mlx5e_devcom_event_mpv,
                                                      priv);
-       if (IS_ERR_OR_NULL(priv->devcom))
-               return -EOPNOTSUPP;
+       if (IS_ERR(priv->devcom))
+               return PTR_ERR(priv->devcom);
 
        if (mlx5_core_is_mp_master(priv->mdev)) {
                mlx5_devcom_send_event(priv->devcom, MPV_DEVCOM_MASTER_UP,
index 1f60954c12f7257cacf0c7e46539c949ac6eaf7b..844d3e3a65ddf04c6e326127b1b1c05ed351b3a7 100644 (file)
@@ -3060,7 +3060,7 @@ void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw, u64 key)
                                                     key,
                                                     mlx5_esw_offloads_devcom_event,
                                                     esw);
-       if (IS_ERR_OR_NULL(esw->devcom))
+       if (IS_ERR(esw->devcom))
                return;
 
        mlx5_devcom_send_event(esw->devcom,
index d14459e5c04fc515ad682e11ee322aa3891e382f..69d482f7c5a29916688ac0d79d324df5f2596586 100644 (file)
@@ -703,8 +703,10 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev)
                return err;
        }
 
-       if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags))
+       if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags)) {
                mlx5_lag_port_sel_destroy(ldev);
+               ldev->buckets = 1;
+       }
        if (mlx5_lag_has_drop_rule(ldev))
                mlx5_lag_drop_rule_cleanup(ldev);
 
index e7d59cfa8708e1617f78b28974977a9588026d1f..7b0766c89f4cf0aac5560e9eb041e564d6531e65 100644 (file)
@@ -220,7 +220,7 @@ mlx5_devcom_register_component(struct mlx5_devcom_dev *devc,
        struct mlx5_devcom_comp *comp;
 
        if (IS_ERR_OR_NULL(devc))
-               return NULL;
+               return ERR_PTR(-EINVAL);
 
        mutex_lock(&comp_list_lock);
        comp = devcom_component_get(devc, id, key, handler);
index 5b28084e8a03c77936e180a06246f9ef0a8dc4bd..dd5d186dc6148f065b986ee5d2363940314816db 100644 (file)
@@ -213,8 +213,8 @@ static int sd_register(struct mlx5_core_dev *dev)
        sd = mlx5_get_sd(dev);
        devcom = mlx5_devcom_register_component(dev->priv.devc, MLX5_DEVCOM_SD_GROUP,
                                                sd->group_id, NULL, dev);
-       if (!devcom)
-               return -ENOMEM;
+       if (IS_ERR(devcom))
+               return PTR_ERR(devcom);
 
        sd->devcom = devcom;
 
index 59806553889e907f7ff2938af2063b1e3b73ca1e..331ce47f51a17a386213d88db9aa7b3cb15d6b41 100644 (file)
@@ -956,7 +956,7 @@ static void mlx5_register_hca_devcom_comp(struct mlx5_core_dev *dev)
                mlx5_devcom_register_component(dev->priv.devc, MLX5_DEVCOM_HCA_PORTS,
                                               mlx5_query_nic_system_image_guid(dev),
                                               NULL, dev);
-       if (IS_ERR_OR_NULL(dev->priv.hca_devcom_comp))
+       if (IS_ERR(dev->priv.hca_devcom_comp))
                mlx5_core_err(dev, "Failed to register devcom HCA component\n");
 }
 
@@ -1699,12 +1699,15 @@ int mlx5_init_one_light(struct mlx5_core_dev *dev)
        err = mlx5_devlink_params_register(priv_to_devlink(dev));
        if (err) {
                mlx5_core_warn(dev, "mlx5_devlink_param_reg err = %d\n", err);
-               goto query_hca_caps_err;
+               goto params_reg_err;
        }
 
        devl_unlock(devlink);
        return 0;
 
+params_reg_err:
+       devl_unregister(devlink);
+       devl_unlock(devlink);
 query_hca_caps_err:
        devl_unregister(devlink);
        devl_unlock(devlink);
index e3bf8c7e4baa62e336415e495a8a385e1edb0654..7ebe712808275a7a1db290040d86c2cd5983c9d7 100644 (file)
@@ -75,7 +75,6 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
                goto peer_devlink_set_err;
        }
 
-       devlink_register(devlink);
        return 0;
 
 peer_devlink_set_err:
index e4d7739bd7c888fc774aeb82a5ece0ed894497d8..4a79c0d7e7ad8546aae5e51f7c23ce7ee8642674 100644 (file)
@@ -849,7 +849,7 @@ free_skb:
 
 static const struct mlxsw_listener mlxsw_emad_rx_listener =
        MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false,
-                 EMAD, DISCARD);
+                 EMAD, FORWARD);
 
 static int mlxsw_emad_tlv_enable(struct mlxsw_core *mlxsw_core)
 {
index 53b150b7ae4e708080cf152c1260983f4cbfc54e..6c06b0592760845f19311fdf4f91672f9209daef 100644 (file)
@@ -1357,24 +1357,20 @@ static struct mlxsw_linecards_event_ops mlxsw_env_event_ops = {
        .got_inactive = mlxsw_env_got_inactive,
 };
 
-static int mlxsw_env_max_module_eeprom_len_query(struct mlxsw_env *mlxsw_env)
+static void mlxsw_env_max_module_eeprom_len_query(struct mlxsw_env *mlxsw_env)
 {
        char mcam_pl[MLXSW_REG_MCAM_LEN];
-       bool mcia_128b_supported;
+       bool mcia_128b_supported = false;
        int err;
 
        mlxsw_reg_mcam_pack(mcam_pl,
                            MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES);
        err = mlxsw_reg_query(mlxsw_env->core, MLXSW_REG(mcam), mcam_pl);
-       if (err)
-               return err;
-
-       mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_MCIA_128B,
-                             &mcia_128b_supported);
+       if (!err)
+               mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_MCIA_128B,
+                                     &mcia_128b_supported);
 
        mlxsw_env->max_eeprom_len = mcia_128b_supported ? 128 : 48;
-
-       return 0;
 }
 
 int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
@@ -1445,15 +1441,11 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
        if (err)
                goto err_type_set;
 
-       err = mlxsw_env_max_module_eeprom_len_query(env);
-       if (err)
-               goto err_eeprom_len_query;
-
+       mlxsw_env_max_module_eeprom_len_query(env);
        env->line_cards[0]->active = true;
 
        return 0;
 
-err_eeprom_len_query:
 err_type_set:
        mlxsw_env_module_event_disable(env, 0);
 err_mlxsw_env_module_event_enable:
index af99bf17eb36de0793b008c063c2a93c6c5b22c8..f42a1b1c9368733d2623643ac6abdd8ffe9b9aff 100644 (file)
@@ -1530,7 +1530,7 @@ mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
 {
        struct pci_dev *pdev = mlxsw_pci->pdev;
        char mcam_pl[MLXSW_REG_MCAM_LEN];
-       bool pci_reset_supported;
+       bool pci_reset_supported = false;
        u32 sys_status;
        int err;
 
@@ -1548,11 +1548,9 @@ mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
        mlxsw_reg_mcam_pack(mcam_pl,
                            MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES);
        err = mlxsw_reg_query(mlxsw_pci->core, MLXSW_REG(mcam), mcam_pl);
-       if (err)
-               return err;
-
-       mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_PCI_RESET,
-                             &pci_reset_supported);
+       if (!err)
+               mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_PCI_RESET,
+                                     &pci_reset_supported);
 
        if (pci_reset_supported) {
                pci_dbg(pdev, "Starting PCI reset flow\n");
index f20052776b3f2e9a3ac7181921a12c3858abea4b..92a406f02eae746b4244ca56619fb75c1a2f9d93 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/netdevice.h>
 #include <linux/mutex.h>
 #include <linux/refcount.h>
+#include <linux/idr.h>
 #include <net/devlink.h>
 #include <trace/events/mlxsw.h>
 
@@ -58,41 +59,43 @@ int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
 static int mlxsw_sp_acl_tcam_region_id_get(struct mlxsw_sp_acl_tcam *tcam,
                                           u16 *p_id)
 {
-       u16 id;
+       int id;
 
-       id = find_first_zero_bit(tcam->used_regions, tcam->max_regions);
-       if (id < tcam->max_regions) {
-               __set_bit(id, tcam->used_regions);
-               *p_id = id;
-               return 0;
-       }
-       return -ENOBUFS;
+       id = ida_alloc_max(&tcam->used_regions, tcam->max_regions - 1,
+                          GFP_KERNEL);
+       if (id < 0)
+               return id;
+
+       *p_id = id;
+
+       return 0;
 }
 
 static void mlxsw_sp_acl_tcam_region_id_put(struct mlxsw_sp_acl_tcam *tcam,
                                            u16 id)
 {
-       __clear_bit(id, tcam->used_regions);
+       ida_free(&tcam->used_regions, id);
 }
 
 static int mlxsw_sp_acl_tcam_group_id_get(struct mlxsw_sp_acl_tcam *tcam,
                                          u16 *p_id)
 {
-       u16 id;
+       int id;
 
-       id = find_first_zero_bit(tcam->used_groups, tcam->max_groups);
-       if (id < tcam->max_groups) {
-               __set_bit(id, tcam->used_groups);
-               *p_id = id;
-               return 0;
-       }
-       return -ENOBUFS;
+       id = ida_alloc_max(&tcam->used_groups, tcam->max_groups - 1,
+                          GFP_KERNEL);
+       if (id < 0)
+               return id;
+
+       *p_id = id;
+
+       return 0;
 }
 
 static void mlxsw_sp_acl_tcam_group_id_put(struct mlxsw_sp_acl_tcam *tcam,
                                           u16 id)
 {
-       __clear_bit(id, tcam->used_groups);
+       ida_free(&tcam->used_groups, id);
 }
 
 struct mlxsw_sp_acl_tcam_pattern {
@@ -715,7 +718,9 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
                             rehash.dw.work);
        int credits = MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS;
 
+       mutex_lock(&vregion->lock);
        mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion, &credits);
+       mutex_unlock(&vregion->lock);
        if (credits < 0)
                /* Rehash gone out of credits so it was interrupted.
                 * Schedule the work as soon as possible to continue.
@@ -725,6 +730,17 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
                mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion);
 }
 
+static void
+mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+{
+       /* The entry markers are relative to the current chunk and therefore
+        * needs to be reset together with the chunk marker.
+        */
+       ctx->current_vchunk = NULL;
+       ctx->start_ventry = NULL;
+       ctx->stop_ventry = NULL;
+}
+
 static void
 mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(struct mlxsw_sp_acl_tcam_vchunk *vchunk)
 {
@@ -747,7 +763,7 @@ mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(struct mlxsw_sp_acl_tcam_vregion *v
         * the current chunk pointer to make sure all chunks
         * are properly migrated.
         */
-       vregion->rehash.ctx.current_vchunk = NULL;
+       mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(&vregion->rehash.ctx);
 }
 
 static struct mlxsw_sp_acl_tcam_vregion *
@@ -820,10 +836,14 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp,
        struct mlxsw_sp_acl_tcam *tcam = vregion->tcam;
 
        if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) {
+               struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx;
+
                mutex_lock(&tcam->lock);
                list_del(&vregion->tlist);
                mutex_unlock(&tcam->lock);
-               cancel_delayed_work_sync(&vregion->rehash.dw);
+               if (cancel_delayed_work_sync(&vregion->rehash.dw) &&
+                   ctx->hints_priv)
+                       ops->region_rehash_hints_put(ctx->hints_priv);
        }
        mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion);
        if (vregion->region2)
@@ -1154,8 +1174,14 @@ mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp,
                                      struct mlxsw_sp_acl_tcam_ventry *ventry,
                                      bool *activity)
 {
-       return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp,
-                                                   ventry->entry, activity);
+       struct mlxsw_sp_acl_tcam_vregion *vregion = ventry->vchunk->vregion;
+       int err;
+
+       mutex_lock(&vregion->lock);
+       err = mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, ventry->entry,
+                                                  activity);
+       mutex_unlock(&vregion->lock);
+       return err;
 }
 
 static int
@@ -1189,6 +1215,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_start(struct mlxsw_sp *mlxsw_sp,
 {
        struct mlxsw_sp_acl_tcam_chunk *new_chunk;
 
+       WARN_ON(vchunk->chunk2);
+
        new_chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region);
        if (IS_ERR(new_chunk))
                return PTR_ERR(new_chunk);
@@ -1207,7 +1235,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_end(struct mlxsw_sp *mlxsw_sp,
 {
        mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
        vchunk->chunk2 = NULL;
-       ctx->current_vchunk = NULL;
+       mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
 }
 
 static int
@@ -1230,6 +1258,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
                return 0;
        }
 
+       if (list_empty(&vchunk->ventry_list))
+               goto out;
+
        /* If the migration got interrupted, we have the ventry to start from
         * stored in context.
         */
@@ -1239,6 +1270,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
                ventry = list_first_entry(&vchunk->ventry_list,
                                          typeof(*ventry), list);
 
+       WARN_ON(ventry->vchunk != vchunk);
+
        list_for_each_entry_from(ventry, &vchunk->ventry_list, list) {
                /* During rollback, once we reach the ventry that failed
                 * to migrate, we are done.
@@ -1279,6 +1312,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
                }
        }
 
+out:
        mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk, ctx);
        return 0;
 }
@@ -1292,6 +1326,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
        struct mlxsw_sp_acl_tcam_vchunk *vchunk;
        int err;
 
+       if (list_empty(&vregion->vchunk_list))
+               return 0;
+
        /* If the migration got interrupted, we have the vchunk
         * we are working on stored in context.
         */
@@ -1320,16 +1357,17 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
        int err, err2;
 
        trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion);
-       mutex_lock(&vregion->lock);
        err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
                                                   ctx, credits);
        if (err) {
+               if (ctx->this_is_rollback)
+                       return err;
                /* In case migration was not successful, we need to swap
                 * so the original region pointer is assigned again
                 * to vregion->region.
                 */
                swap(vregion->region, vregion->region2);
-               ctx->current_vchunk = NULL;
+               mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
                ctx->this_is_rollback = true;
                err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
                                                            ctx, credits);
@@ -1340,7 +1378,6 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
                        /* Let the rollback to be continued later on. */
                }
        }
-       mutex_unlock(&vregion->lock);
        trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion);
        return err;
 }
@@ -1389,6 +1426,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp,
 
        ctx->hints_priv = hints_priv;
        ctx->this_is_rollback = false;
+       mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
 
        return 0;
 
@@ -1441,7 +1479,8 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
        err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion,
                                                ctx, credits);
        if (err) {
-               dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n");
+               dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n");
+               return;
        }
 
        if (*credits >= 0)
@@ -1549,19 +1588,11 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
        if (max_tcam_regions < max_regions)
                max_regions = max_tcam_regions;
 
-       tcam->used_regions = bitmap_zalloc(max_regions, GFP_KERNEL);
-       if (!tcam->used_regions) {
-               err = -ENOMEM;
-               goto err_alloc_used_regions;
-       }
+       ida_init(&tcam->used_regions);
        tcam->max_regions = max_regions;
 
        max_groups = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_GROUPS);
-       tcam->used_groups = bitmap_zalloc(max_groups, GFP_KERNEL);
-       if (!tcam->used_groups) {
-               err = -ENOMEM;
-               goto err_alloc_used_groups;
-       }
+       ida_init(&tcam->used_groups);
        tcam->max_groups = max_groups;
        tcam->max_group_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
                                                  ACL_MAX_GROUP_SIZE);
@@ -1575,10 +1606,8 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
        return 0;
 
 err_tcam_init:
-       bitmap_free(tcam->used_groups);
-err_alloc_used_groups:
-       bitmap_free(tcam->used_regions);
-err_alloc_used_regions:
+       ida_destroy(&tcam->used_groups);
+       ida_destroy(&tcam->used_regions);
        mlxsw_sp_acl_tcam_rehash_params_unregister(mlxsw_sp);
 err_rehash_params_register:
        mutex_destroy(&tcam->lock);
@@ -1591,8 +1620,8 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
        const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
 
        ops->fini(mlxsw_sp, tcam->priv);
-       bitmap_free(tcam->used_groups);
-       bitmap_free(tcam->used_regions);
+       ida_destroy(&tcam->used_groups);
+       ida_destroy(&tcam->used_regions);
        mlxsw_sp_acl_tcam_rehash_params_unregister(mlxsw_sp);
        mutex_destroy(&tcam->lock);
 }
index 462bf448497d33b74618c1f78001c0924c666dd5..79a1d8606512531730c2da490e01f47ac0fc6399 100644 (file)
@@ -6,15 +6,16 @@
 
 #include <linux/list.h>
 #include <linux/parman.h>
+#include <linux/idr.h>
 
 #include "reg.h"
 #include "spectrum.h"
 #include "core_acl_flex_keys.h"
 
 struct mlxsw_sp_acl_tcam {
-       unsigned long *used_regions; /* bit array */
+       struct ida used_regions;
        unsigned int max_regions;
-       unsigned long *used_groups;  /* bit array */
+       struct ida used_groups;
        unsigned int max_groups;
        unsigned int max_group_size;
        struct mutex lock; /* guards vregion list */
index 523e0c470894f7fdcf8a995fb821ff146f08fcd9..55f255a3c9db69b92d5743bd42c34cbaba46a0a8 100644 (file)
@@ -36,6 +36,27 @@ struct sparx5_tc_flower_template {
        u16 l3_proto; /* protocol specified in the template */
 };
 
+/* SparX-5 VCAP fragment types:
+ * 0 = no fragment, 1 = initial fragment,
+ * 2 = suspicious fragment, 3 = valid follow-up fragment
+ */
+enum {                   /* key / mask */
+       FRAG_NOT   = 0x03, /* 0 / 3 */
+       FRAG_SOME  = 0x11, /* 1 / 1 */
+       FRAG_FIRST = 0x13, /* 1 / 3 */
+       FRAG_LATER = 0x33, /* 3 / 3 */
+       FRAG_INVAL = 0xff, /* invalid */
+};
+
+/* Flower fragment flag to VCAP fragment type mapping */
+static const u8 sparx5_vcap_frag_map[4][4] = {           /* is_frag */
+       { FRAG_INVAL, FRAG_INVAL, FRAG_INVAL, FRAG_FIRST }, /* 0/0 */
+       { FRAG_NOT,   FRAG_NOT,   FRAG_INVAL, FRAG_INVAL }, /* 0/1 */
+       { FRAG_INVAL, FRAG_INVAL, FRAG_INVAL, FRAG_INVAL }, /* 1/0 */
+       { FRAG_SOME,  FRAG_LATER, FRAG_INVAL, FRAG_FIRST }  /* 1/1 */
+       /* 0/0        0/1         1/0         1/1 <-- first_frag */
+};
+
 static int
 sparx5_tc_flower_es0_tpid(struct vcap_tc_flower_parse_usage *st)
 {
@@ -145,29 +166,27 @@ sparx5_tc_flower_handler_control_usage(struct vcap_tc_flower_parse_usage *st)
        flow_rule_match_control(st->frule, &mt);
 
        if (mt.mask->flags) {
-               if (mt.mask->flags & FLOW_DIS_FIRST_FRAG) {
-                       if (mt.key->flags & FLOW_DIS_FIRST_FRAG) {
-                               value = 1; /* initial fragment */
-                               mask = 0x3;
-                       } else {
-                               if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) {
-                                       value = 3; /* follow up fragment */
-                                       mask = 0x3;
-                               } else {
-                                       value = 0; /* no fragment */
-                                       mask = 0x3;
-                               }
-                       }
-               } else {
-                       if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) {
-                               value = 3; /* follow up fragment */
-                               mask = 0x3;
-                       } else {
-                               value = 0; /* no fragment */
-                               mask = 0x3;
-                       }
+               u8 is_frag_key = !!(mt.key->flags & FLOW_DIS_IS_FRAGMENT);
+               u8 is_frag_mask = !!(mt.mask->flags & FLOW_DIS_IS_FRAGMENT);
+               u8 is_frag_idx = (is_frag_key << 1) | is_frag_mask;
+
+               u8 first_frag_key = !!(mt.key->flags & FLOW_DIS_FIRST_FRAG);
+               u8 first_frag_mask = !!(mt.mask->flags & FLOW_DIS_FIRST_FRAG);
+               u8 first_frag_idx = (first_frag_key << 1) | first_frag_mask;
+
+               /* Lookup verdict based on the 2 + 2 input bits */
+               u8 vdt = sparx5_vcap_frag_map[is_frag_idx][first_frag_idx];
+
+               if (vdt == FRAG_INVAL) {
+                       NL_SET_ERR_MSG_MOD(st->fco->common.extack,
+                                          "Match on invalid fragment flag combination");
+                       return -EINVAL;
                }
 
+               /* Extract VCAP fragment key and mask from verdict */
+               value = (vdt >> 4) & 0x3;
+               mask = vdt & 0x3;
+
                err = vcap_rule_add_key_u32(st->vrule,
                                            VCAP_KF_L3_FRAGMENT_TYPE,
                                            value, mask);
index a5ac21a0ee33ff01e8bcdcf5757a76a863d6543b..cb6b33a228ea2063edd4f795a1f3368d1fbc483a 100644 (file)
@@ -1868,8 +1868,8 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
                            struct flow_cls_offload *f)
 {
        struct qede_arfs_fltr_node *n;
-       int min_hlen, rc = -EINVAL;
        struct qede_arfs_tuple t;
+       int min_hlen, rc;
 
        __qede_lock(edev);
 
@@ -1879,7 +1879,8 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
        }
 
        /* parse flower attribute and prepare filter */
-       if (qede_parse_flow_attr(edev, proto, f->rule, &t))
+       rc = qede_parse_flow_attr(edev, proto, f->rule, &t);
+       if (rc)
                goto unlock;
 
        /* Validate profile mode and number of filters */
@@ -1888,11 +1889,13 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
                DP_NOTICE(edev,
                          "Filter configuration invalidated, filter mode=0x%x, configured mode=0x%x, filter count=0x%x\n",
                          t.mode, edev->arfs->mode, edev->arfs->filter_count);
+               rc = -EINVAL;
                goto unlock;
        }
 
        /* parse tc actions and get the vf_id */
-       if (qede_parse_actions(edev, &f->rule->action, f->common.extack))
+       rc = qede_parse_actions(edev, &f->rule->action, f->common.extack);
+       if (rc)
                goto unlock;
 
        if (qede_flow_find_fltr(edev, &t)) {
@@ -1998,10 +2001,9 @@ static int qede_flow_spec_to_rule(struct qede_dev *edev,
        if (IS_ERR(flow))
                return PTR_ERR(flow);
 
-       if (qede_parse_flow_attr(edev, proto, flow->rule, t)) {
-               err = -EINVAL;
+       err = qede_parse_flow_attr(edev, proto, flow->rule, t);
+       if (err)
                goto err_out;
-       }
 
        /* Make sure location is valid and filter isn't already set */
        err = qede_flow_spec_validate(edev, &flow->rule->action, t,
index ba01c8cc3c906d5ea9a02029dc76fabc243b277c..9b1f639f64a10cfe89255996bb43d68771f38e5e 100644 (file)
@@ -769,25 +769,28 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q)
        dma_addr_t dma_addr;
        int rx_packets = 0;
        u8  desc_status;
-       u16 pkt_len;
+       u16 desc_len;
        u8  die_dt;
        int entry;
        int limit;
        int i;
 
-       entry = priv->cur_rx[q] % priv->num_rx_ring[q];
        limit = priv->dirty_rx[q] + priv->num_rx_ring[q] - priv->cur_rx[q];
        stats = &priv->stats[q];
 
-       desc = &priv->rx_ring[q].desc[entry];
-       for (i = 0; i < limit && rx_packets < *quota && desc->die_dt != DT_FEMPTY; i++) {
+       for (i = 0; i < limit; i++, priv->cur_rx[q]++) {
+               entry = priv->cur_rx[q] % priv->num_rx_ring[q];
+               desc = &priv->rx_ring[q].desc[entry];
+               if (rx_packets == *quota || desc->die_dt == DT_FEMPTY)
+                       break;
+
                /* Descriptor type must be checked before all other reads */
                dma_rmb();
                desc_status = desc->msc;
-               pkt_len = le16_to_cpu(desc->ds_cc) & RX_DS;
+               desc_len = le16_to_cpu(desc->ds_cc) & RX_DS;
 
                /* We use 0-byte descriptors to mark the DMA mapping errors */
-               if (!pkt_len)
+               if (!desc_len)
                        continue;
 
                if (desc_status & MSC_MC)
@@ -808,25 +811,25 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q)
                        switch (die_dt) {
                        case DT_FSINGLE:
                                skb = ravb_get_skb_gbeth(ndev, entry, desc);
-                               skb_put(skb, pkt_len);
+                               skb_put(skb, desc_len);
                                skb->protocol = eth_type_trans(skb, ndev);
                                if (ndev->features & NETIF_F_RXCSUM)
                                        ravb_rx_csum_gbeth(skb);
                                napi_gro_receive(&priv->napi[q], skb);
                                rx_packets++;
-                               stats->rx_bytes += pkt_len;
+                               stats->rx_bytes += desc_len;
                                break;
                        case DT_FSTART:
                                priv->rx_1st_skb = ravb_get_skb_gbeth(ndev, entry, desc);
-                               skb_put(priv->rx_1st_skb, pkt_len);
+                               skb_put(priv->rx_1st_skb, desc_len);
                                break;
                        case DT_FMID:
                                skb = ravb_get_skb_gbeth(ndev, entry, desc);
                                skb_copy_to_linear_data_offset(priv->rx_1st_skb,
                                                               priv->rx_1st_skb->len,
                                                               skb->data,
-                                                              pkt_len);
-                               skb_put(priv->rx_1st_skb, pkt_len);
+                                                              desc_len);
+                               skb_put(priv->rx_1st_skb, desc_len);
                                dev_kfree_skb(skb);
                                break;
                        case DT_FEND:
@@ -834,23 +837,20 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q)
                                skb_copy_to_linear_data_offset(priv->rx_1st_skb,
                                                               priv->rx_1st_skb->len,
                                                               skb->data,
-                                                              pkt_len);
-                               skb_put(priv->rx_1st_skb, pkt_len);
+                                                              desc_len);
+                               skb_put(priv->rx_1st_skb, desc_len);
                                dev_kfree_skb(skb);
                                priv->rx_1st_skb->protocol =
                                        eth_type_trans(priv->rx_1st_skb, ndev);
                                if (ndev->features & NETIF_F_RXCSUM)
-                                       ravb_rx_csum_gbeth(skb);
+                                       ravb_rx_csum_gbeth(priv->rx_1st_skb);
+                               stats->rx_bytes += priv->rx_1st_skb->len;
                                napi_gro_receive(&priv->napi[q],
                                                 priv->rx_1st_skb);
                                rx_packets++;
-                               stats->rx_bytes += pkt_len;
                                break;
                        }
                }
-
-               entry = (++priv->cur_rx[q]) % priv->num_rx_ring[q];
-               desc = &priv->rx_ring[q].desc[entry];
        }
 
        /* Refill the RX ring buffers. */
@@ -891,30 +891,29 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q)
 {
        struct ravb_private *priv = netdev_priv(ndev);
        const struct ravb_hw_info *info = priv->info;
-       int entry = priv->cur_rx[q] % priv->num_rx_ring[q];
-       int boguscnt = (priv->dirty_rx[q] + priv->num_rx_ring[q]) -
-                       priv->cur_rx[q];
        struct net_device_stats *stats = &priv->stats[q];
        struct ravb_ex_rx_desc *desc;
+       unsigned int limit, i;
        struct sk_buff *skb;
        dma_addr_t dma_addr;
        struct timespec64 ts;
+       int rx_packets = 0;
        u8  desc_status;
        u16 pkt_len;
-       int limit;
+       int entry;
+
+       limit = priv->dirty_rx[q] + priv->num_rx_ring[q] - priv->cur_rx[q];
+       for (i = 0; i < limit; i++, priv->cur_rx[q]++) {
+               entry = priv->cur_rx[q] % priv->num_rx_ring[q];
+               desc = &priv->rx_ring[q].ex_desc[entry];
+               if (rx_packets == *quota || desc->die_dt == DT_FEMPTY)
+                       break;
 
-       boguscnt = min(boguscnt, *quota);
-       limit = boguscnt;
-       desc = &priv->rx_ring[q].ex_desc[entry];
-       while (desc->die_dt != DT_FEMPTY) {
                /* Descriptor type must be checked before all other reads */
                dma_rmb();
                desc_status = desc->msc;
                pkt_len = le16_to_cpu(desc->ds_cc) & RX_DS;
 
-               if (--boguscnt < 0)
-                       break;
-
                /* We use 0-byte descriptors to mark the DMA mapping errors */
                if (!pkt_len)
                        continue;
@@ -960,12 +959,9 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q)
                        if (ndev->features & NETIF_F_RXCSUM)
                                ravb_rx_csum(skb);
                        napi_gro_receive(&priv->napi[q], skb);
-                       stats->rx_packets++;
+                       rx_packets++;
                        stats->rx_bytes += pkt_len;
                }
-
-               entry = (++priv->cur_rx[q]) % priv->num_rx_ring[q];
-               desc = &priv->rx_ring[q].ex_desc[entry];
        }
 
        /* Refill the RX ring buffers. */
@@ -995,9 +991,9 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q)
                desc->die_dt = DT_FEMPTY;
        }
 
-       *quota -= limit - (++boguscnt);
-
-       return boguscnt <= 0;
+       stats->rx_packets += rx_packets;
+       *quota -= rx_packets;
+       return *quota == 0;
 }
 
 /* Packet receive function for Ethernet AVB */
@@ -2726,19 +2722,18 @@ static int ravb_setup_irq(struct ravb_private *priv, const char *irq_name,
        struct platform_device *pdev = priv->pdev;
        struct net_device *ndev = priv->ndev;
        struct device *dev = &pdev->dev;
-       const char *dev_name;
+       const char *devname = dev_name(dev);
        unsigned long flags;
        int error, irq_num;
 
        if (irq_name) {
-               dev_name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", ndev->name, ch);
-               if (!dev_name)
+               devname = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", devname, ch);
+               if (!devname)
                        return -ENOMEM;
 
                irq_num = platform_get_irq_byname(pdev, irq_name);
                flags = 0;
        } else {
-               dev_name = ndev->name;
                irq_num = platform_get_irq(pdev, 0);
                flags = IRQF_SHARED;
        }
@@ -2748,9 +2743,9 @@ static int ravb_setup_irq(struct ravb_private *priv, const char *irq_name,
        if (irq)
                *irq = irq_num;
 
-       error = devm_request_irq(dev, irq_num, handler, flags, dev_name, ndev);
+       error = devm_request_irq(dev, irq_num, handler, flags, devname, ndev);
        if (error)
-               netdev_err(ndev, "cannot request IRQ %s\n", dev_name);
+               netdev_err(ndev, "cannot request IRQ %s\n", devname);
 
        return error;
 }
index a6fefe675ef1520566ccdcafaac705f0ee159e42..3b7d4ac1e7be07cb2a0fc796f73b671ed535f01d 100644 (file)
@@ -553,6 +553,7 @@ extern const struct stmmac_hwtimestamp stmmac_ptp;
 extern const struct stmmac_mode_ops dwmac4_ring_mode_ops;
 
 struct mac_link {
+       u32 caps;
        u32 speed_mask;
        u32 speed10;
        u32 speed100;
index b21d99faa2d04c985427af61724dd073e3a2fe79..e1b761dcfa1dd56f2e5218312933eb1ea6bc06b1 100644 (file)
@@ -1096,6 +1096,8 @@ static struct mac_device_info *sun8i_dwmac_setup(void *ppriv)
 
        priv->dev->priv_flags |= IFF_UNICAST_FLT;
 
+       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+                        MAC_10 | MAC_100 | MAC_1000;
        /* The loopback bit seems to be re-set when link change
         * Simply mask it each time
         * Speed 10/100/1000 are set in BIT(2)/BIT(3)
index 3927609abc44110be97903aee12e25084473b80c..8555299443f4edf2475b95c1785544a1c3b73251 100644 (file)
@@ -539,6 +539,8 @@ int dwmac1000_setup(struct stmmac_priv *priv)
        if (mac->multicast_filter_bins)
                mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
+       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+                        MAC_10 | MAC_100 | MAC_1000;
        mac->link.duplex = GMAC_CONTROL_DM;
        mac->link.speed10 = GMAC_CONTROL_PS;
        mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
index a6e8d7bd95886fc277c7e22c896ddf618e0fca97..7667d103cd0ebd9670a42360a095cfd322c8ebac 100644 (file)
@@ -175,6 +175,8 @@ int dwmac100_setup(struct stmmac_priv *priv)
        dev_info(priv->device, "\tDWMAC100\n");
 
        mac->pcsr = priv->ioaddr;
+       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+                        MAC_10 | MAC_100;
        mac->link.duplex = MAC_CONTROL_F;
        mac->link.speed10 = 0;
        mac->link.speed100 = 0;
index cef25efbdff99fdc07a313ab678869e83c85f79e..a38226d7cc6a99e45c39f62c81c56d8dc87a921a 100644 (file)
@@ -70,7 +70,10 @@ static void dwmac4_core_init(struct mac_device_info *hw,
 
 static void dwmac4_phylink_get_caps(struct stmmac_priv *priv)
 {
-       priv->phylink_config.mac_capabilities |= MAC_2500FD;
+       if (priv->plat->tx_queues_to_use > 1)
+               priv->hw->link.caps &= ~(MAC_10HD | MAC_100HD | MAC_1000HD);
+       else
+               priv->hw->link.caps |= (MAC_10HD | MAC_100HD | MAC_1000HD);
 }
 
 static void dwmac4_rx_queue_enable(struct mac_device_info *hw,
@@ -1378,6 +1381,8 @@ int dwmac4_setup(struct stmmac_priv *priv)
        if (mac->multicast_filter_bins)
                mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
+       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+                        MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
        mac->link.duplex = GMAC_CONFIG_DM;
        mac->link.speed10 = GMAC_CONFIG_PS;
        mac->link.speed100 = GMAC_CONFIG_FES | GMAC_CONFIG_PS;
index e841e312077ef0604c5b17a5473069cc4affadff..f8e7775bb63364c589da99cb4c954a38f4411567 100644 (file)
@@ -47,14 +47,6 @@ static void dwxgmac2_core_init(struct mac_device_info *hw,
        writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN);
 }
 
-static void xgmac_phylink_get_caps(struct stmmac_priv *priv)
-{
-       priv->phylink_config.mac_capabilities |= MAC_2500FD | MAC_5000FD |
-                                                MAC_10000FD | MAC_25000FD |
-                                                MAC_40000FD | MAC_50000FD |
-                                                MAC_100000FD;
-}
-
 static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable)
 {
        u32 tx = readl(ioaddr + XGMAC_TX_CONFIG);
@@ -1540,7 +1532,6 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *
 
 const struct stmmac_ops dwxgmac210_ops = {
        .core_init = dwxgmac2_core_init,
-       .phylink_get_caps = xgmac_phylink_get_caps,
        .set_mac = dwxgmac2_set_mac,
        .rx_ipc = dwxgmac2_rx_ipc,
        .rx_queue_enable = dwxgmac2_rx_queue_enable,
@@ -1601,7 +1592,6 @@ static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
 
 const struct stmmac_ops dwxlgmac2_ops = {
        .core_init = dwxgmac2_core_init,
-       .phylink_get_caps = xgmac_phylink_get_caps,
        .set_mac = dwxgmac2_set_mac,
        .rx_ipc = dwxgmac2_rx_ipc,
        .rx_queue_enable = dwxlgmac2_rx_queue_enable,
@@ -1661,6 +1651,9 @@ int dwxgmac2_setup(struct stmmac_priv *priv)
        if (mac->multicast_filter_bins)
                mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
+       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+                        MAC_1000FD | MAC_2500FD | MAC_5000FD |
+                        MAC_10000FD;
        mac->link.duplex = 0;
        mac->link.speed10 = XGMAC_CONFIG_SS_10_MII;
        mac->link.speed100 = XGMAC_CONFIG_SS_100_MII;
@@ -1698,6 +1691,11 @@ int dwxlgmac2_setup(struct stmmac_priv *priv)
        if (mac->multicast_filter_bins)
                mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
+       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+                        MAC_1000FD | MAC_2500FD | MAC_5000FD |
+                        MAC_10000FD | MAC_25000FD |
+                        MAC_40000FD | MAC_50000FD |
+                        MAC_100000FD;
        mac->link.duplex = 0;
        mac->link.speed1000 = XLGMAC_CONFIG_SS_1000;
        mac->link.speed2500 = XLGMAC_CONFIG_SS_2500;
index 24cd80490d19cf86c2cd566b81f13b137109d784..7c6fb14b555508e4461980f99843ac461b323239 100644 (file)
@@ -1198,17 +1198,6 @@ static int stmmac_init_phy(struct net_device *dev)
        return ret;
 }
 
-static void stmmac_set_half_duplex(struct stmmac_priv *priv)
-{
-       /* Half-Duplex can only work with single tx queue */
-       if (priv->plat->tx_queues_to_use > 1)
-               priv->phylink_config.mac_capabilities &=
-                       ~(MAC_10HD | MAC_100HD | MAC_1000HD);
-       else
-               priv->phylink_config.mac_capabilities |=
-                       (MAC_10HD | MAC_100HD | MAC_1000HD);
-}
-
 static int stmmac_phy_setup(struct stmmac_priv *priv)
 {
        struct stmmac_mdio_bus_data *mdio_bus_data;
@@ -1236,15 +1225,11 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
                xpcs_get_interfaces(priv->hw->xpcs,
                                    priv->phylink_config.supported_interfaces);
 
-       priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
-                                               MAC_10FD | MAC_100FD |
-                                               MAC_1000FD;
-
-       stmmac_set_half_duplex(priv);
-
        /* Get the MAC specific capabilities */
        stmmac_mac_phylink_get_caps(priv);
 
+       priv->phylink_config.mac_capabilities = priv->hw->link.caps;
+
        max_speed = priv->plat->max_speed;
        if (max_speed)
                phylink_limit_mac_speed(&priv->phylink_config, max_speed);
@@ -7342,6 +7327,7 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
        int ret = 0, i;
+       int max_speed;
 
        if (netif_running(dev))
                stmmac_release(dev);
@@ -7355,7 +7341,14 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
                        priv->rss.table[i] = ethtool_rxfh_indir_default(i,
                                                                        rx_cnt);
 
-       stmmac_set_half_duplex(priv);
+       stmmac_mac_phylink_get_caps(priv);
+
+       priv->phylink_config.mac_capabilities = priv->hw->link.caps;
+
+       max_speed = priv->plat->max_speed;
+       if (max_speed)
+               phylink_limit_mac_speed(&priv->phylink_config, max_speed);
+
        stmmac_napi_add(dev);
 
        if (netif_running(dev))
index 2939a21ca74f3cf0f627981df74a949e9c61011e..1d00e21808c1c36dde2fcd4e6a864ca1ecf72a0b 100644 (file)
@@ -2793,6 +2793,8 @@ static void am65_cpsw_unregister_devlink(struct am65_cpsw_common *common)
 
 static int am65_cpsw_nuss_register_ndevs(struct am65_cpsw_common *common)
 {
+       struct am65_cpsw_rx_chn *rx_chan = &common->rx_chns;
+       struct am65_cpsw_tx_chn *tx_chan = common->tx_chns;
        struct device *dev = common->dev;
        struct am65_cpsw_port *port;
        int ret = 0, i;
@@ -2805,6 +2807,22 @@ static int am65_cpsw_nuss_register_ndevs(struct am65_cpsw_common *common)
        if (ret)
                return ret;
 
+       /* The DMA Channels are not guaranteed to be in a clean state.
+        * Reset and disable them to ensure that they are back to the
+        * clean state and ready to be used.
+        */
+       for (i = 0; i < common->tx_ch_num; i++) {
+               k3_udma_glue_reset_tx_chn(tx_chan[i].tx_chn, &tx_chan[i],
+                                         am65_cpsw_nuss_tx_cleanup);
+               k3_udma_glue_disable_tx_chn(tx_chan[i].tx_chn);
+       }
+
+       for (i = 0; i < AM65_CPSW_MAX_RX_FLOWS; i++)
+               k3_udma_glue_reset_rx_chn(rx_chan->rx_chn, i, rx_chan,
+                                         am65_cpsw_nuss_rx_cleanup, !!i);
+
+       k3_udma_glue_disable_rx_chn(rx_chan->rx_chn);
+
        ret = am65_cpsw_nuss_register_devlink(common);
        if (ret)
                return ret;
index c66618d91c28fe2bdf9886b3c476bdb014cd5fe5..f89716b1cfb640577d7ca009adfb99e9b9f00c54 100644 (file)
@@ -784,6 +784,11 @@ static bool am65_cpts_match_tx_ts(struct am65_cpts *cpts,
                struct am65_cpts_skb_cb_data *skb_cb =
                                        (struct am65_cpts_skb_cb_data *)skb->cb;
 
+               if ((ptp_classify_raw(skb) & PTP_CLASS_V1) &&
+                   ((mtype_seqid & AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK) ==
+                    (skb_cb->skb_mtype_seqid & AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK)))
+                       mtype_seqid = skb_cb->skb_mtype_seqid;
+
                if (mtype_seqid == skb_cb->skb_mtype_seqid) {
                        u64 ns = event->timestamp;
 
index cf7b73f8f450728930587dc0646a0bbaa1d2b476..b69af69a1ccd3614ab0051b3c7675ab6a42a7872 100644 (file)
@@ -421,12 +421,14 @@ static int prueth_init_rx_chns(struct prueth_emac *emac,
                if (!i)
                        fdqring_id = k3_udma_glue_rx_flow_get_fdq_id(rx_chn->rx_chn,
                                                                     i);
-               rx_chn->irq[i] = k3_udma_glue_rx_get_irq(rx_chn->rx_chn, i);
-               if (rx_chn->irq[i] <= 0) {
-                       ret = rx_chn->irq[i];
+               ret = k3_udma_glue_rx_get_irq(rx_chn->rx_chn, i);
+               if (ret <= 0) {
+                       if (!ret)
+                               ret = -ENXIO;
                        netdev_err(ndev, "Failed to get rx dma irq");
                        goto fail;
                }
+               rx_chn->irq[i] = ret;
        }
 
        return 0;
index 6dff2c85682d8bcdd97ca614447e205919d5decd..6fae161cbcb822614a8f36935559f364ee0a7dc8 100644 (file)
@@ -1598,7 +1598,7 @@ static void wx_set_num_queues(struct wx *wx)
  */
 static int wx_acquire_msix_vectors(struct wx *wx)
 {
-       struct irq_affinity affd = {0, };
+       struct irq_affinity affd = { .pre_vectors = 1 };
        int nvecs, i;
 
        /* We start by asking for one vector per queue pair */
index 2fa511227eac8490314c09821c7b6f1e1fdfed43..93295916b1d2b80751637dee4a0006688958c428 100644 (file)
@@ -20,8 +20,6 @@
 #include "txgbe_phy.h"
 #include "txgbe_hw.h"
 
-#define TXGBE_I2C_CLK_DEV_NAME "i2c_dw"
-
 static int txgbe_swnodes_register(struct txgbe *txgbe)
 {
        struct txgbe_nodes *nodes = &txgbe->nodes;
@@ -573,8 +571,8 @@ static int txgbe_clock_register(struct txgbe *txgbe)
        char clk_name[32];
        struct clk *clk;
 
-       snprintf(clk_name, sizeof(clk_name), "%s.%d",
-                TXGBE_I2C_CLK_DEV_NAME, pci_dev_id(pdev));
+       snprintf(clk_name, sizeof(clk_name), "i2c_designware.%d",
+                pci_dev_id(pdev));
 
        clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000);
        if (IS_ERR(clk))
@@ -636,7 +634,7 @@ static int txgbe_i2c_register(struct txgbe *txgbe)
 
        info.parent = &pdev->dev;
        info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_I2C]);
-       info.name = TXGBE_I2C_CLK_DEV_NAME;
+       info.name = "i2c_designware";
        info.id = pci_dev_id(pdev);
 
        info.res = &DEFINE_RES_IRQ(pdev->irq);
index ba4704c2c640b860c55655607f8dd5cc044cfa3e..e62d6cbdf9bc6458064c7c0852fc23db095ae642 100644 (file)
@@ -1098,11 +1098,12 @@ out_hashtable:
 static void gtp_dellink(struct net_device *dev, struct list_head *head)
 {
        struct gtp_dev *gtp = netdev_priv(dev);
+       struct hlist_node *next;
        struct pdp_ctx *pctx;
        int i;
 
        for (i = 0; i < gtp->hash_size; i++)
-               hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i], hlist_tid)
+               hlist_for_each_entry_safe(pctx, next, &gtp->tid_hash[i], hlist_tid)
                        pdp_context_delete(pctx);
 
        list_del_rcu(&gtp->list);
index 0206b84284ab5e0c95981ff86fa4b2a2a14c5c51..ff016c11b4a0383b6653a37ef4bc6344fff3f703 100644 (file)
@@ -999,10 +999,12 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
        struct metadata_dst *md_dst;
        struct macsec_rxh_data *rxd;
        struct macsec_dev *macsec;
+       bool is_macsec_md_dst;
 
        rcu_read_lock();
        rxd = macsec_data_rcu(skb->dev);
        md_dst = skb_metadata_dst(skb);
+       is_macsec_md_dst = md_dst && md_dst->type == METADATA_MACSEC;
 
        list_for_each_entry_rcu(macsec, &rxd->secys, secys) {
                struct sk_buff *nskb;
@@ -1013,14 +1015,42 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
                 * the SecTAG, so we have to deduce which port to deliver to.
                 */
                if (macsec_is_offloaded(macsec) && netif_running(ndev)) {
-                       struct macsec_rx_sc *rx_sc = NULL;
+                       const struct macsec_ops *ops;
 
-                       if (md_dst && md_dst->type == METADATA_MACSEC)
-                               rx_sc = find_rx_sc(&macsec->secy, md_dst->u.macsec_info.sci);
+                       ops = macsec_get_ops(macsec, NULL);
 
-                       if (md_dst && md_dst->type == METADATA_MACSEC && !rx_sc)
+                       if (ops->rx_uses_md_dst && !is_macsec_md_dst)
                                continue;
 
+                       if (is_macsec_md_dst) {
+                               struct macsec_rx_sc *rx_sc;
+
+                               /* All drivers that implement MACsec offload
+                                * support using skb metadata destinations must
+                                * indicate that they do so.
+                                */
+                               DEBUG_NET_WARN_ON_ONCE(!ops->rx_uses_md_dst);
+                               rx_sc = find_rx_sc(&macsec->secy,
+                                                  md_dst->u.macsec_info.sci);
+                               if (!rx_sc)
+                                       continue;
+                               /* device indicated macsec offload occurred */
+                               skb->dev = ndev;
+                               skb->pkt_type = PACKET_HOST;
+                               eth_skb_pkt_type(skb, ndev);
+                               ret = RX_HANDLER_ANOTHER;
+                               goto out;
+                       }
+
+                       /* This datapath is insecure because it is unable to
+                        * enforce isolation of broadcast/multicast traffic and
+                        * unicast traffic with promiscuous mode on the macsec
+                        * netdev. Since the core stack has no mechanism to
+                        * check that the hardware did indeed receive MACsec
+                        * traffic, it is possible that the response handling
+                        * done by the MACsec port was to a plaintext packet.
+                        * This violates the MACsec protocol standard.
+                        */
                        if (ether_addr_equal_64bits(hdr->h_dest,
                                                    ndev->dev_addr)) {
                                /* exact match, divert skb to this port */
@@ -1036,14 +1066,10 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
                                        break;
 
                                nskb->dev = ndev;
-                               if (ether_addr_equal_64bits(hdr->h_dest,
-                                                           ndev->broadcast))
-                                       nskb->pkt_type = PACKET_BROADCAST;
-                               else
-                                       nskb->pkt_type = PACKET_MULTICAST;
+                               eth_skb_pkt_type(nskb, ndev);
 
                                __netif_rx(nskb);
-                       } else if (rx_sc || ndev->flags & IFF_PROMISC) {
+                       } else if (ndev->flags & IFF_PROMISC) {
                                skb->dev = ndev;
                                skb->pkt_type = PACKET_HOST;
                                ret = RX_HANDLER_ANOTHER;
index fa8c6fdcf30181067c7c3f164e997171908a70b8..d7aaefb5226b62ad5de3c3783c189b8f45b1a7c2 100644 (file)
@@ -695,7 +695,8 @@ static int dp83869_configure_mode(struct phy_device *phydev,
        phy_ctrl_val = dp83869->mode;
        if (phydev->interface == PHY_INTERFACE_MODE_MII) {
                if (dp83869->mode == DP83869_100M_MEDIA_CONVERT ||
-                   dp83869->mode == DP83869_RGMII_100_BASE) {
+                   dp83869->mode == DP83869_RGMII_100_BASE ||
+                   dp83869->mode == DP83869_RGMII_COPPER_ETHERNET) {
                        phy_ctrl_val |= DP83869_OP_MODE_MII;
                } else {
                        phydev_err(phydev, "selected op-mode is not valid with MII mode\n");
index 0f3a1538a8b8ee045953a3c5ff308dc824ea7c0a..f4f9412d0cd7e256f4b2e962dd18974e1120c0fb 100644 (file)
 #define   MTK_PHY_LED_ON_LINK1000              BIT(0)
 #define   MTK_PHY_LED_ON_LINK100               BIT(1)
 #define   MTK_PHY_LED_ON_LINK10                        BIT(2)
+#define   MTK_PHY_LED_ON_LINK                  (MTK_PHY_LED_ON_LINK10 |\
+                                                MTK_PHY_LED_ON_LINK100 |\
+                                                MTK_PHY_LED_ON_LINK1000)
 #define   MTK_PHY_LED_ON_LINKDOWN              BIT(3)
 #define   MTK_PHY_LED_ON_FDX                   BIT(4) /* Full duplex */
 #define   MTK_PHY_LED_ON_HDX                   BIT(5) /* Half duplex */
 #define   MTK_PHY_LED_BLINK_100RX              BIT(3)
 #define   MTK_PHY_LED_BLINK_10TX               BIT(4)
 #define   MTK_PHY_LED_BLINK_10RX               BIT(5)
+#define   MTK_PHY_LED_BLINK_RX                 (MTK_PHY_LED_BLINK_10RX |\
+                                                MTK_PHY_LED_BLINK_100RX |\
+                                                MTK_PHY_LED_BLINK_1000RX)
+#define   MTK_PHY_LED_BLINK_TX                 (MTK_PHY_LED_BLINK_10TX |\
+                                                MTK_PHY_LED_BLINK_100TX |\
+                                                MTK_PHY_LED_BLINK_1000TX)
 #define   MTK_PHY_LED_BLINK_COLLISION          BIT(6)
 #define   MTK_PHY_LED_BLINK_RX_CRC_ERR         BIT(7)
 #define   MTK_PHY_LED_BLINK_RX_IDLE_ERR                BIT(8)
@@ -1247,11 +1256,9 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
        if (blink < 0)
                return -EIO;
 
-       if ((on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 |
-                  MTK_PHY_LED_ON_LINK10)) ||
-           (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX |
-                     MTK_PHY_LED_BLINK_10RX | MTK_PHY_LED_BLINK_1000TX |
-                     MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX)))
+       if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX |
+                  MTK_PHY_LED_ON_LINKDOWN)) ||
+           (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX)))
                set_bit(bit_netdev, &priv->led_state);
        else
                clear_bit(bit_netdev, &priv->led_state);
@@ -1269,7 +1276,7 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
        if (!rules)
                return 0;
 
-       if (on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 | MTK_PHY_LED_ON_LINK10))
+       if (on & MTK_PHY_LED_ON_LINK)
                *rules |= BIT(TRIGGER_NETDEV_LINK);
 
        if (on & MTK_PHY_LED_ON_LINK10)
@@ -1287,10 +1294,10 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
        if (on & MTK_PHY_LED_ON_HDX)
                *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
 
-       if (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX | MTK_PHY_LED_BLINK_10RX))
+       if (blink & MTK_PHY_LED_BLINK_RX)
                *rules |= BIT(TRIGGER_NETDEV_RX);
 
-       if (blink & (MTK_PHY_LED_BLINK_1000TX | MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX))
+       if (blink & MTK_PHY_LED_BLINK_TX)
                *rules |= BIT(TRIGGER_NETDEV_TX);
 
        return 0;
@@ -1323,15 +1330,19 @@ static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
                on |= MTK_PHY_LED_ON_LINK1000;
 
        if (rules & BIT(TRIGGER_NETDEV_RX)) {
-               blink |= MTK_PHY_LED_BLINK_10RX  |
-                        MTK_PHY_LED_BLINK_100RX |
-                        MTK_PHY_LED_BLINK_1000RX;
+               blink |= (on & MTK_PHY_LED_ON_LINK) ?
+                         (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10RX : 0) |
+                          ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100RX : 0) |
+                          ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000RX : 0)) :
+                         MTK_PHY_LED_BLINK_RX;
        }
 
        if (rules & BIT(TRIGGER_NETDEV_TX)) {
-               blink |= MTK_PHY_LED_BLINK_10TX  |
-                        MTK_PHY_LED_BLINK_100TX |
-                        MTK_PHY_LED_BLINK_1000TX;
+               blink |= (on & MTK_PHY_LED_ON_LINK) ?
+                         (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10TX : 0) |
+                          ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100TX : 0) |
+                          ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000TX : 0)) :
+                         MTK_PHY_LED_BLINK_TX;
        }
 
        if (blink || on)
@@ -1344,9 +1355,7 @@ static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
                                MTK_PHY_LED0_ON_CTRL,
                             MTK_PHY_LED_ON_FDX     |
                             MTK_PHY_LED_ON_HDX     |
-                            MTK_PHY_LED_ON_LINK10  |
-                            MTK_PHY_LED_ON_LINK100 |
-                            MTK_PHY_LED_ON_LINK1000,
+                            MTK_PHY_LED_ON_LINK,
                             on);
 
        if (ret)
index 0b3f21cba552f27221a2c7fbe8147feb34e69724..92da8c03d960c9beca5b425a1e3d366f37fa21fc 100644 (file)
@@ -2125,14 +2125,16 @@ static ssize_t tun_put_user(struct tun_struct *tun,
                                            tun_is_little_endian(tun), true,
                                            vlan_hlen)) {
                        struct skb_shared_info *sinfo = skb_shinfo(skb);
-                       pr_err("unexpected GSO type: "
-                              "0x%x, gso_size %d, hdr_len %d\n",
-                              sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size),
-                              tun16_to_cpu(tun, gso.hdr_len));
-                       print_hex_dump(KERN_ERR, "tun: ",
-                                      DUMP_PREFIX_NONE,
-                                      16, 1, skb->head,
-                                      min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true);
+
+                       if (net_ratelimit()) {
+                               netdev_err(tun->dev, "unexpected GSO type: 0x%x, gso_size %d, hdr_len %d\n",
+                                          sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size),
+                                          tun16_to_cpu(tun, gso.hdr_len));
+                               print_hex_dump(KERN_ERR, "tun: ",
+                                              DUMP_PREFIX_NONE,
+                                              16, 1, skb->head,
+                                              min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true);
+                       }
                        WARN_ON_ONCE(1);
                        return -EINVAL;
                }
index a9c418890a1cacc584c9265f4716fa2e18fe0e4b..df9d767cb524241848c744504d6e2999efc42ed5 100644 (file)
@@ -1317,6 +1317,8 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
 
        netif_set_tso_max_size(dev->net, 16384);
 
+       ax88179_reset(dev);
+
        return 0;
 }
 
@@ -1454,21 +1456,16 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                        /* Skip IP alignment pseudo header */
                        skb_pull(skb, 2);
 
-                       skb->truesize = SKB_TRUESIZE(pkt_len_plus_padd);
                        ax88179_rx_checksum(skb, pkt_hdr);
                        return 1;
                }
 
-               ax_skb = skb_clone(skb, GFP_ATOMIC);
+               ax_skb = netdev_alloc_skb_ip_align(dev->net, pkt_len);
                if (!ax_skb)
                        return 0;
-               skb_trim(ax_skb, pkt_len);
-
-               /* Skip IP alignment pseudo header */
-               skb_pull(ax_skb, 2);
+               skb_put(ax_skb, pkt_len);
+               memcpy(ax_skb->data, skb->data + 2, pkt_len);
 
-               skb->truesize = pkt_len_plus_padd +
-                               SKB_DATA_ALIGN(sizeof(struct sk_buff));
                ax88179_rx_checksum(ax_skb, pkt_hdr);
                usbnet_skb_return(dev, ax_skb);
 
@@ -1695,7 +1692,6 @@ static const struct driver_info ax88179_info = {
        .unbind = ax88179_unbind,
        .status = ax88179_status,
        .link_reset = ax88179_link_reset,
-       .reset = ax88179_reset,
        .stop = ax88179_stop,
        .flags = FLAG_ETHER | FLAG_FRAMING_AX,
        .rx_fixup = ax88179_rx_fixup,
@@ -1708,7 +1704,6 @@ static const struct driver_info ax88178a_info = {
        .unbind = ax88179_unbind,
        .status = ax88179_status,
        .link_reset = ax88179_link_reset,
-       .reset = ax88179_reset,
        .stop = ax88179_stop,
        .flags = FLAG_ETHER | FLAG_FRAMING_AX,
        .rx_fixup = ax88179_rx_fixup,
index e2e181378f4124c64b1d02bbe910f6209b57a356..a5469cf5cf6706de2c3ded24f675f504c794227c 100644 (file)
@@ -1368,6 +1368,9 @@ static const struct usb_device_id products[] = {
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1060, 2)}, /* Telit LN920 */
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1070, 2)}, /* Telit FN990 */
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1080, 2)}, /* Telit FE990 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a0, 0)}, /* Telit FN920C04 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a4, 0)}, /* Telit FN920C04 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a9, 0)}, /* Telit FN920C04 */
        {QMI_FIXED_INTF(0x1bc7, 0x1100, 3)},    /* Telit ME910 */
        {QMI_FIXED_INTF(0x1bc7, 0x1101, 3)},    /* Telit ME910 dual modem */
        {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},    /* Telit LE920 */
@@ -1431,6 +1434,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x2692, 0x9025, 4)},    /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */
        {QMI_QUIRK_SET_DTR(0x1546, 0x1312, 4)}, /* u-blox LARA-R6 01B */
        {QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */
+       {QMI_QUIRK_SET_DTR(0x33f8, 0x0104, 4)}, /* Rolling RW101 RMNET */
 
        /* 4. Gobi 1000 devices */
        {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},    /* Acer Gobi Modem Device */
index 3495591a5c29b2aa929fcf307c2970c661ec2ea6..3a9148fb1422ba5bedcbfe368fb611fc60732f66 100644 (file)
@@ -1615,6 +1615,10 @@ static bool vxlan_set_mac(struct vxlan_dev *vxlan,
        if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))
                return false;
 
+       /* Ignore packets from invalid src-address */
+       if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
+               return false;
+
        /* Get address from the outer IP header */
        if (vxlan_get_sk_family(vs) == AF_INET) {
                saddr.sin.sin_addr.s_addr = ip_hdr(skb)->saddr;
@@ -1670,6 +1674,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
        bool raw_proto = false;
        void *oiph;
        __be32 vni = 0;
+       int nh;
 
        /* Need UDP and VXLAN header to be present */
        if (!pskb_may_pull(skb, VXLAN_HLEN))
@@ -1758,12 +1763,28 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
                skb->pkt_type = PACKET_HOST;
        }
 
-       oiph = skb_network_header(skb);
+       /* Save offset of outer header relative to skb->head,
+        * because we are going to reset the network header to the inner header
+        * and might change skb->head.
+        */
+       nh = skb_network_header(skb) - skb->head;
+
        skb_reset_network_header(skb);
 
+       if (!pskb_inet_may_pull(skb)) {
+               DEV_STATS_INC(vxlan->dev, rx_length_errors);
+               DEV_STATS_INC(vxlan->dev, rx_errors);
+               vxlan_vnifilter_count(vxlan, vni, vninode,
+                                     VXLAN_VNI_STATS_RX_ERRORS, 0);
+               goto drop;
+       }
+
+       /* Get the outer header. */
+       oiph = skb->head + nh;
+
        if (!vxlan_ecn_decapsulate(vs, oiph, skb)) {
-               ++vxlan->dev->stats.rx_frame_errors;
-               ++vxlan->dev->stats.rx_errors;
+               DEV_STATS_INC(vxlan->dev, rx_frame_errors);
+               DEV_STATS_INC(vxlan->dev, rx_errors);
                vxlan_vnifilter_count(vxlan, vni, vninode,
                                      VXLAN_VNI_STATS_RX_ERRORS, 0);
                goto drop;
@@ -1833,7 +1854,9 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
                goto out;
 
        if (!pskb_may_pull(skb, arp_hdr_len(dev))) {
-               dev->stats.tx_dropped++;
+               dev_core_stats_tx_dropped_inc(dev);
+               vxlan_vnifilter_count(vxlan, vni, NULL,
+                                     VXLAN_VNI_STATS_TX_DROPS, 0);
                goto out;
        }
        parp = arp_hdr(skb);
@@ -1889,7 +1912,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
                reply->pkt_type = PACKET_HOST;
 
                if (netif_rx(reply) == NET_RX_DROP) {
-                       dev->stats.rx_dropped++;
+                       dev_core_stats_rx_dropped_inc(dev);
                        vxlan_vnifilter_count(vxlan, vni, NULL,
                                              VXLAN_VNI_STATS_RX_DROPS, 0);
                }
@@ -2048,7 +2071,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
                        goto out;
 
                if (netif_rx(reply) == NET_RX_DROP) {
-                       dev->stats.rx_dropped++;
+                       dev_core_stats_rx_dropped_inc(dev);
                        vxlan_vnifilter_count(vxlan, vni, NULL,
                                              VXLAN_VNI_STATS_RX_DROPS, 0);
                }
@@ -2259,7 +2282,7 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
                                      len);
        } else {
 drop:
-               dev->stats.rx_dropped++;
+               dev_core_stats_rx_dropped_inc(dev);
                vxlan_vnifilter_count(dst_vxlan, vni, NULL,
                                      VXLAN_VNI_STATS_RX_DROPS, 0);
        }
@@ -2291,7 +2314,7 @@ static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
                                           addr_family, dst_port,
                                           vxlan->cfg.flags);
                if (!dst_vxlan) {
-                       dev->stats.tx_errors++;
+                       DEV_STATS_INC(dev, tx_errors);
                        vxlan_vnifilter_count(vxlan, vni, NULL,
                                              VXLAN_VNI_STATS_TX_ERRORS, 0);
                        kfree_skb(skb);
@@ -2555,7 +2578,7 @@ out_unlock:
        return;
 
 drop:
-       dev->stats.tx_dropped++;
+       dev_core_stats_tx_dropped_inc(dev);
        vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_DROPS, 0);
        dev_kfree_skb(skb);
        return;
@@ -2563,11 +2586,11 @@ drop:
 tx_error:
        rcu_read_unlock();
        if (err == -ELOOP)
-               dev->stats.collisions++;
+               DEV_STATS_INC(dev, collisions);
        else if (err == -ENETUNREACH)
-               dev->stats.tx_carrier_errors++;
+               DEV_STATS_INC(dev, tx_carrier_errors);
        dst_release(ndst);
-       dev->stats.tx_errors++;
+       DEV_STATS_INC(dev, tx_errors);
        vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_ERRORS, 0);
        kfree_skb(skb);
 }
@@ -2600,7 +2623,7 @@ static void vxlan_xmit_nh(struct sk_buff *skb, struct net_device *dev,
        return;
 
 drop:
-       dev->stats.tx_dropped++;
+       dev_core_stats_tx_dropped_inc(dev);
        vxlan_vnifilter_count(netdev_priv(dev), vni, NULL,
                              VXLAN_VNI_STATS_TX_DROPS, 0);
        dev_kfree_skb(skb);
@@ -2638,7 +2661,7 @@ static netdev_tx_t vxlan_xmit_nhid(struct sk_buff *skb, struct net_device *dev,
        return NETDEV_TX_OK;
 
 drop:
-       dev->stats.tx_dropped++;
+       dev_core_stats_tx_dropped_inc(dev);
        vxlan_vnifilter_count(netdev_priv(dev), vni, NULL,
                              VXLAN_VNI_STATS_TX_DROPS, 0);
        dev_kfree_skb(skb);
@@ -2735,7 +2758,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
                            !is_multicast_ether_addr(eth->h_dest))
                                vxlan_fdb_miss(vxlan, eth->h_dest);
 
-                       dev->stats.tx_dropped++;
+                       dev_core_stats_tx_dropped_inc(dev);
                        vxlan_vnifilter_count(vxlan, vni, NULL,
                                              VXLAN_VNI_STATS_TX_DROPS, 0);
                        kfree_skb(skb);
index a6a37d67a50ad552b4185af654289d635c2cfd70..9f4bf41a3d41e4e1395aa77fb6874130e5783d96 100644 (file)
@@ -9020,6 +9020,7 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
        offload = &arvif->arp_ns_offload;
        count = 0;
 
+       /* Note: read_lock_bh() calls rcu_read_lock() */
        read_lock_bh(&idev->lock);
 
        memset(offload->ipv6_addr, 0, sizeof(offload->ipv6_addr));
@@ -9050,7 +9051,8 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
        }
 
        /* get anycast address */
-       for (ifaca6 = idev->ac_list; ifaca6; ifaca6 = ifaca6->aca_next) {
+       for (ifaca6 = rcu_dereference(idev->ac_list); ifaca6;
+            ifaca6 = rcu_dereference(ifaca6->aca_next)) {
                if (count >= ATH11K_IPV6_MAX_COUNT)
                        goto generate;
 
index 072b0a5827d19f801d9f0da38933aef21044b7fc..eca1457caa0cad9eb13edce501beba6d5540fe57 100644 (file)
@@ -10,7 +10,7 @@
 #include "fw/api/txq.h"
 
 /* Highest firmware API version supported */
-#define IWL_BZ_UCODE_API_MAX   90
+#define IWL_BZ_UCODE_API_MAX   89
 
 /* Lowest firmware API version supported */
 #define IWL_BZ_UCODE_API_MIN   80
index 9b79279fd76cad94170d28614b7eee0729ac02f8..dbbcb2d0968c0992d15f652409cf651dc625428c 100644 (file)
@@ -10,7 +10,7 @@
 #include "fw/api/txq.h"
 
 /* Highest firmware API version supported */
-#define IWL_SC_UCODE_API_MAX   90
+#define IWL_SC_UCODE_API_MAX   89
 
 /* Lowest firmware API version supported */
 #define IWL_SC_UCODE_API_MIN   82
index 4863a3c746406ed70a398d8939e080e72636fa0b..d84d7e955bb021fc1994d1b5fa9e21183e01027a 100644 (file)
@@ -53,6 +53,8 @@ int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        if (!pasn)
                return -ENOBUFS;
 
+       iwl_mvm_ftm_remove_pasn_sta(mvm, addr);
+
        pasn->cipher = iwl_mvm_cipher_to_location_cipher(cipher);
 
        switch (pasn->cipher) {
index 9f69e04594e49cb59f3102071c905bd75b93f825..fe5bba8561d0c69abeef30221c5cc040f64c7b96 100644 (file)
@@ -279,6 +279,7 @@ int iwl_mvm_unset_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
        RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id],
                         NULL);
+       iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id);
        return 0;
 }
 
@@ -296,7 +297,6 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                return 0;
 
        cmd.link_id = cpu_to_le32(link_info->fw_link_id);
-       iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id);
        link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
        cmd.spec_link_id = link_conf->link_id;
        cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID);
index f3e3986b4c72f2aabfd9ff67edf8c11a1bebc03c..11559563ae38162e8c138dddc79e0cc89f3b349d 100644 (file)
@@ -2813,7 +2813,8 @@ static int iwl_mvm_build_scan_cmd(struct iwl_mvm *mvm,
                if (ver_handler->version != scan_ver)
                        continue;
 
-               return ver_handler->handler(mvm, vif, params, type, uid);
+               err = ver_handler->handler(mvm, vif, params, type, uid);
+               return err ? : uid;
        }
 
        err = iwl_mvm_scan_umac(mvm, vif, params, type, uid);
index b55fe320633c74b42618d37be6bc40a951f0c898..59e1fc0018df3f32d60e3e52341350c10a44d0f0 100644 (file)
@@ -3899,7 +3899,7 @@ static int hwsim_pmsr_report_nl(struct sk_buff *msg, struct genl_info *info)
        }
 
        nla_for_each_nested(peer, peers, rem) {
-               struct cfg80211_pmsr_result result;
+               struct cfg80211_pmsr_result result = {};
 
                err = mac80211_hwsim_parse_pmsr_result(peer, &result, info);
                if (err)
index 7eb17f46a8153d88705603e421f350b0fd091c2b..9e1a34e23af26e0a2bd7e18b4e3fe5f6726f560d 100644 (file)
@@ -424,7 +424,8 @@ struct trf7970a {
        enum trf7970a_state             state;
        struct device                   *dev;
        struct spi_device               *spi;
-       struct regulator                *regulator;
+       struct regulator                *vin_regulator;
+       struct regulator                *vddio_regulator;
        struct nfc_digital_dev          *ddev;
        u32                             quirks;
        bool                            is_initiator;
@@ -1883,7 +1884,7 @@ static int trf7970a_power_up(struct trf7970a *trf)
        if (trf->state != TRF7970A_ST_PWR_OFF)
                return 0;
 
-       ret = regulator_enable(trf->regulator);
+       ret = regulator_enable(trf->vin_regulator);
        if (ret) {
                dev_err(trf->dev, "%s - Can't enable VIN: %d\n", __func__, ret);
                return ret;
@@ -1926,7 +1927,7 @@ static int trf7970a_power_down(struct trf7970a *trf)
        if (trf->en2_gpiod && !(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW))
                gpiod_set_value_cansleep(trf->en2_gpiod, 0);
 
-       ret = regulator_disable(trf->regulator);
+       ret = regulator_disable(trf->vin_regulator);
        if (ret)
                dev_err(trf->dev, "%s - Can't disable VIN: %d\n", __func__,
                        ret);
@@ -2065,37 +2066,37 @@ static int trf7970a_probe(struct spi_device *spi)
        mutex_init(&trf->lock);
        INIT_DELAYED_WORK(&trf->timeout_work, trf7970a_timeout_work_handler);
 
-       trf->regulator = devm_regulator_get(&spi->dev, "vin");
-       if (IS_ERR(trf->regulator)) {
-               ret = PTR_ERR(trf->regulator);
+       trf->vin_regulator = devm_regulator_get(&spi->dev, "vin");
+       if (IS_ERR(trf->vin_regulator)) {
+               ret = PTR_ERR(trf->vin_regulator);
                dev_err(trf->dev, "Can't get VIN regulator: %d\n", ret);
                goto err_destroy_lock;
        }
 
-       ret = regulator_enable(trf->regulator);
+       ret = regulator_enable(trf->vin_regulator);
        if (ret) {
                dev_err(trf->dev, "Can't enable VIN: %d\n", ret);
                goto err_destroy_lock;
        }
 
-       uvolts = regulator_get_voltage(trf->regulator);
+       uvolts = regulator_get_voltage(trf->vin_regulator);
        if (uvolts > 4000000)
                trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3;
 
-       trf->regulator = devm_regulator_get(&spi->dev, "vdd-io");
-       if (IS_ERR(trf->regulator)) {
-               ret = PTR_ERR(trf->regulator);
+       trf->vddio_regulator = devm_regulator_get(&spi->dev, "vdd-io");
+       if (IS_ERR(trf->vddio_regulator)) {
+               ret = PTR_ERR(trf->vddio_regulator);
                dev_err(trf->dev, "Can't get VDD_IO regulator: %d\n", ret);
-               goto err_destroy_lock;
+               goto err_disable_vin_regulator;
        }
 
-       ret = regulator_enable(trf->regulator);
+       ret = regulator_enable(trf->vddio_regulator);
        if (ret) {
                dev_err(trf->dev, "Can't enable VDD_IO: %d\n", ret);
-               goto err_destroy_lock;
+               goto err_disable_vin_regulator;
        }
 
-       if (regulator_get_voltage(trf->regulator) == 1800000) {
+       if (regulator_get_voltage(trf->vddio_regulator) == 1800000) {
                trf->io_ctrl = TRF7970A_REG_IO_CTRL_IO_LOW;
                dev_dbg(trf->dev, "trf7970a config vdd_io to 1.8V\n");
        }
@@ -2108,7 +2109,7 @@ static int trf7970a_probe(struct spi_device *spi)
        if (!trf->ddev) {
                dev_err(trf->dev, "Can't allocate NFC digital device\n");
                ret = -ENOMEM;
-               goto err_disable_regulator;
+               goto err_disable_vddio_regulator;
        }
 
        nfc_digital_set_parent_dev(trf->ddev, trf->dev);
@@ -2137,8 +2138,10 @@ err_shutdown:
        trf7970a_shutdown(trf);
 err_free_ddev:
        nfc_digital_free_device(trf->ddev);
-err_disable_regulator:
-       regulator_disable(trf->regulator);
+err_disable_vddio_regulator:
+       regulator_disable(trf->vddio_regulator);
+err_disable_vin_regulator:
+       regulator_disable(trf->vin_regulator);
 err_destroy_lock:
        mutex_destroy(&trf->lock);
        return ret;
@@ -2157,7 +2160,8 @@ static void trf7970a_remove(struct spi_device *spi)
        nfc_digital_unregister_device(trf->ddev);
        nfc_digital_free_device(trf->ddev);
 
-       regulator_disable(trf->regulator);
+       regulator_disable(trf->vddio_regulator);
+       regulator_disable(trf->vin_regulator);
 
        mutex_destroy(&trf->lock);
 }
index 27281a9a8951dbd53f30a27a14e0ac0be9a35c5d..095f59e7aa937aa3ae9d8e3fc3f1a25608c99f25 100644 (file)
@@ -628,27 +628,6 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
 }
 EXPORT_SYMBOL_GPL(nvme_change_ctrl_state);
 
-/*
- * Returns true for sink states that can't ever transition back to live.
- */
-static bool nvme_state_terminal(struct nvme_ctrl *ctrl)
-{
-       switch (nvme_ctrl_state(ctrl)) {
-       case NVME_CTRL_NEW:
-       case NVME_CTRL_LIVE:
-       case NVME_CTRL_RESETTING:
-       case NVME_CTRL_CONNECTING:
-               return false;
-       case NVME_CTRL_DELETING:
-       case NVME_CTRL_DELETING_NOIO:
-       case NVME_CTRL_DEAD:
-               return true;
-       default:
-               WARN_ONCE(1, "Unhandled ctrl state:%d", ctrl->state);
-               return true;
-       }
-}
-
 /*
  * Waits for the controller state to be resetting, or returns false if it is
  * not possible to ever transition to that state.
@@ -3681,7 +3660,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
                                "Found shared namespace %d, but multipathing not supported.\n",
                                info->nsid);
                        dev_warn_once(ctrl->device,
-                               "Support for shared namespaces without CONFIG_NVME_MULTIPATH is deprecated and will be removed in Linux 6.0\n.");
+                               "Support for shared namespaces without CONFIG_NVME_MULTIPATH is deprecated and will be removed in Linux 6.0.\n");
                }
        }
 
index 5397fb428b242cea36f8c36997e134f6463e9f39..d16e976ae1a4732efef32a9da1da88be6567f621 100644 (file)
@@ -247,7 +247,8 @@ static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node)
                if (nvme_path_is_disabled(ns))
                        continue;
 
-               if (READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_NUMA)
+               if (ns->ctrl->numa_node != NUMA_NO_NODE &&
+                   READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_NUMA)
                        distance = node_distance(node, ns->ctrl->numa_node);
                else
                        distance = LOCAL_DISTANCE;
index d0ed64dc7380e51577bc6ece92db1d0a273905a7..b564c5f1450c6a506302c482882d2be31a8eb5c6 100644 (file)
@@ -741,6 +741,27 @@ static inline bool nvme_is_aen_req(u16 qid, __u16 command_id)
                nvme_tag_from_cid(command_id) >= NVME_AQ_BLK_MQ_DEPTH;
 }
 
+/*
+ * Returns true for sink states that can't ever transition back to live.
+ */
+static inline bool nvme_state_terminal(struct nvme_ctrl *ctrl)
+{
+       switch (nvme_ctrl_state(ctrl)) {
+       case NVME_CTRL_NEW:
+       case NVME_CTRL_LIVE:
+       case NVME_CTRL_RESETTING:
+       case NVME_CTRL_CONNECTING:
+               return false;
+       case NVME_CTRL_DELETING:
+       case NVME_CTRL_DELETING_NOIO:
+       case NVME_CTRL_DEAD:
+               return true;
+       default:
+               WARN_ONCE(1, "Unhandled ctrl state:%d", ctrl->state);
+               return true;
+       }
+}
+
 void nvme_complete_rq(struct request *req);
 void nvme_complete_batch_req(struct request *req);
 
index 8e0bb9692685d4638bd21dad44fe1fbbbb147a77..e393f6947ce493f8674a7bb971dc4d4abae192ca 100644 (file)
@@ -1286,6 +1286,9 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
        u32 csts = readl(dev->bar + NVME_REG_CSTS);
        u8 opcode;
 
+       if (nvme_state_terminal(&dev->ctrl))
+               goto disable;
+
        /* If PCI error recovery process is happening, we cannot reset or
         * the recovery mechanism will surely fail.
         */
@@ -1390,8 +1393,11 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
        return BLK_EH_RESET_TIMER;
 
 disable:
-       if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING))
+       if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING)) {
+               if (nvme_state_terminal(&dev->ctrl))
+                       nvme_dev_disable(dev, true);
                return BLK_EH_DONE;
+       }
 
        nvme_dev_disable(dev, false);
        if (nvme_try_sched_reset(&dev->ctrl))
index fdbcdcedcee99f064cc7258d22b7fe737d285eda..28bc2f373cfa0e715040a7d4f5a18db4690ca5dc 100644 (file)
@@ -360,12 +360,18 @@ static inline void nvme_tcp_send_all(struct nvme_tcp_queue *queue)
        } while (ret > 0);
 }
 
-static inline bool nvme_tcp_queue_more(struct nvme_tcp_queue *queue)
+static inline bool nvme_tcp_queue_has_pending(struct nvme_tcp_queue *queue)
 {
        return !list_empty(&queue->send_list) ||
                !llist_empty(&queue->req_list);
 }
 
+static inline bool nvme_tcp_queue_more(struct nvme_tcp_queue *queue)
+{
+       return !nvme_tcp_tls(&queue->ctrl->ctrl) &&
+               nvme_tcp_queue_has_pending(queue);
+}
+
 static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req,
                bool sync, bool last)
 {
@@ -386,7 +392,7 @@ static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req,
                mutex_unlock(&queue->send_mutex);
        }
 
-       if (last && nvme_tcp_queue_more(queue))
+       if (last && nvme_tcp_queue_has_pending(queue))
                queue_work_on(queue->io_cpu, nvme_tcp_wq, &queue->io_work);
 }
 
index 3ddbc3880cac8d327074fe8f923b9f257979c8bd..fb518b00f71f6034a74be5746fc30b5bb090b972 100644 (file)
@@ -285,9 +285,9 @@ int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,
        }
 
        if (shash_len != crypto_shash_digestsize(shash_tfm)) {
-               pr_debug("%s: hash len mismatch (len %d digest %d)\n",
-                        __func__, shash_len,
-                        crypto_shash_digestsize(shash_tfm));
+               pr_err("%s: hash len mismatch (len %d digest %d)\n",
+                       __func__, shash_len,
+                       crypto_shash_digestsize(shash_tfm));
                ret = -EINVAL;
                goto out_free_tfm;
        }
@@ -370,7 +370,7 @@ out_free_response:
        nvme_auth_free_key(transformed_key);
 out_free_tfm:
        crypto_free_shash(shash_tfm);
-       return 0;
+       return ret;
 }
 
 int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response,
index a2325330bf22145202837aa5cf89d9ec6543ab59..89a001101a7fca08bf047405aac92704bdd9a4c9 100644 (file)
@@ -754,6 +754,19 @@ static struct configfs_attribute *nvmet_ns_attrs[] = {
        NULL,
 };
 
+bool nvmet_subsys_nsid_exists(struct nvmet_subsys *subsys, u32 nsid)
+{
+       struct config_item *ns_item;
+       char name[4] = {};
+
+       if (sprintf(name, "%u", nsid) <= 0)
+               return false;
+       mutex_lock(&subsys->namespaces_group.cg_subsys->su_mutex);
+       ns_item = config_group_find_item(&subsys->namespaces_group, name);
+       mutex_unlock(&subsys->namespaces_group.cg_subsys->su_mutex);
+       return ns_item != NULL;
+}
+
 static void nvmet_ns_release(struct config_item *item)
 {
        struct nvmet_ns *ns = to_nvmet_ns(item);
index 8860a3eb71ec891e948a34060f34b4b148553418..e06013c5dace94d8b91960451b868fe6eaac2137 100644 (file)
@@ -437,10 +437,13 @@ void nvmet_stop_keep_alive_timer(struct nvmet_ctrl *ctrl)
 u16 nvmet_req_find_ns(struct nvmet_req *req)
 {
        u32 nsid = le32_to_cpu(req->cmd->common.nsid);
+       struct nvmet_subsys *subsys = nvmet_req_subsys(req);
 
-       req->ns = xa_load(&nvmet_req_subsys(req)->namespaces, nsid);
+       req->ns = xa_load(&subsys->namespaces, nsid);
        if (unlikely(!req->ns)) {
                req->error_loc = offsetof(struct nvme_common_command, nsid);
+               if (nvmet_subsys_nsid_exists(subsys, nsid))
+                       return NVME_SC_INTERNAL_PATH_ERROR;
                return NVME_SC_INVALID_NS | NVME_SC_DNR;
        }
 
index f460728e1df1fd87e24969e782203c7684a23326..c1306de1f4ddf650c2ee66167559f27e4004e837 100644 (file)
@@ -543,6 +543,7 @@ void nvmet_subsys_disc_changed(struct nvmet_subsys *subsys,
                struct nvmet_host *host);
 void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u8 event_type,
                u8 event_info, u8 log_page);
+bool nvmet_subsys_nsid_exists(struct nvmet_subsys *subsys, u32 nsid);
 
 #define NVMET_MIN_QUEUE_SIZE   16
 #define NVMET_MAX_QUEUE_SIZE   1024
index a5422e2c979addca1f219777b47f61f5817e302a..380f22ee3ebba3ef5fe50108b39ea78345c1f1ba 100644 (file)
@@ -348,6 +348,7 @@ static int nvmet_tcp_check_ddgst(struct nvmet_tcp_queue *queue, void *pdu)
        return 0;
 }
 
+/* If cmd buffers are NULL, no operation is performed */
 static void nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd *cmd)
 {
        kfree(cmd->iov);
@@ -1581,13 +1582,9 @@ static void nvmet_tcp_free_cmd_data_in_buffers(struct nvmet_tcp_queue *queue)
        struct nvmet_tcp_cmd *cmd = queue->cmds;
        int i;
 
-       for (i = 0; i < queue->nr_cmds; i++, cmd++) {
-               if (nvmet_tcp_need_data_in(cmd))
-                       nvmet_tcp_free_cmd_buffers(cmd);
-       }
-
-       if (!queue->nr_cmds && nvmet_tcp_need_data_in(&queue->connect))
-               nvmet_tcp_free_cmd_buffers(&queue->connect);
+       for (i = 0; i < queue->nr_cmds; i++, cmd++)
+               nvmet_tcp_free_cmd_buffers(cmd);
+       nvmet_tcp_free_cmd_buffers(&queue->connect);
 }
 
 static void nvmet_tcp_release_queue_work(struct work_struct *w)
index b700f52b7b6799f92c1c66f8c737efaae7a47dfc..11fcb1867118c3662c9a9b7f6c103dca5af4c768 100644 (file)
@@ -110,8 +110,10 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
                /* Source clock from SoC internal PLL */
                writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
                       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062);
-               writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
-                      imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
+               if (imx8_phy->drvdata->variant != IMX8MM) {
+                       writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
+                              imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
+               }
                val = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
                writel(val | ANA_AUX_RX_TERM_GND_EN,
                       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064);
index 41162d7228c919dadc65c526657e120eff268f59..1d1db1737422a8edd29cf63201ee244270ee1e69 100644 (file)
@@ -603,7 +603,7 @@ static void comphy_gbe_phy_init(struct mvebu_a3700_comphy_lane *lane,
        u16 val;
 
        fix_idx = 0;
-       for (addr = 0; addr < 512; addr++) {
+       for (addr = 0; addr < ARRAY_SIZE(gbe_phy_init); addr++) {
                /*
                 * All PHY register values are defined in full for 3.125Gbps
                 * SERDES speed. The values required for 1.25 Gbps are almost
@@ -611,11 +611,12 @@ static void comphy_gbe_phy_init(struct mvebu_a3700_comphy_lane *lane,
                 * comparison to 3.125 Gbps values. These register values are
                 * stored in "gbe_phy_init_fix" array.
                 */
-               if (!is_1gbps && gbe_phy_init_fix[fix_idx].addr == addr) {
+               if (!is_1gbps &&
+                   fix_idx < ARRAY_SIZE(gbe_phy_init_fix) &&
+                   gbe_phy_init_fix[fix_idx].addr == addr) {
                        /* Use new value */
                        val = gbe_phy_init_fix[fix_idx].value;
-                       if (fix_idx < ARRAY_SIZE(gbe_phy_init_fix))
-                               fix_idx++;
+                       fix_idx++;
                } else {
                        val = gbe_phy_init[addr];
                }
index 03fb0d4b75d744492e4646af65287f61e7927f1b..20d4c020a83c1f7566533e0e8de5b7cd796415ad 100644 (file)
@@ -297,7 +297,7 @@ static int m31usb_phy_probe(struct platform_device *pdev)
                return dev_err_probe(dev, PTR_ERR(qphy->phy),
                                     "failed to create phy\n");
 
-       qphy->vreg = devm_regulator_get(dev, "vdda-phy");
+       qphy->vreg = devm_regulator_get(dev, "vdd");
        if (IS_ERR(qphy->vreg))
                return dev_err_probe(dev, PTR_ERR(qphy->vreg),
                                     "failed to get vreg\n");
index 7d585a4bbbba950c803412d829bed4140d57d898..c21cdb8dbfe746061acea9b9ec1ab516d05cd3d3 100644 (file)
@@ -77,6 +77,7 @@ enum qphy_reg_layout {
        QPHY_COM_BIAS_EN_CLKBUFLR_EN,
 
        QPHY_DP_PHY_STATUS,
+       QPHY_DP_PHY_VCO_DIV,
 
        QPHY_TX_TX_POL_INV,
        QPHY_TX_TX_DRV_LVL,
@@ -102,6 +103,7 @@ static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
        [QPHY_COM_BIAS_EN_CLKBUFLR_EN]  = QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN,
 
        [QPHY_DP_PHY_STATUS]            = QSERDES_V3_DP_PHY_STATUS,
+       [QPHY_DP_PHY_VCO_DIV]           = QSERDES_V3_DP_PHY_VCO_DIV,
 
        [QPHY_TX_TX_POL_INV]            = QSERDES_V3_TX_TX_POL_INV,
        [QPHY_TX_TX_DRV_LVL]            = QSERDES_V3_TX_TX_DRV_LVL,
@@ -126,6 +128,7 @@ static const unsigned int qmp_v45_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
        [QPHY_COM_BIAS_EN_CLKBUFLR_EN]  = QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN,
 
        [QPHY_DP_PHY_STATUS]            = QSERDES_V4_DP_PHY_STATUS,
+       [QPHY_DP_PHY_VCO_DIV]           = QSERDES_V4_DP_PHY_VCO_DIV,
 
        [QPHY_TX_TX_POL_INV]            = QSERDES_V4_TX_TX_POL_INV,
        [QPHY_TX_TX_DRV_LVL]            = QSERDES_V4_TX_TX_DRV_LVL,
@@ -150,6 +153,7 @@ static const unsigned int qmp_v5_5nm_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
        [QPHY_COM_BIAS_EN_CLKBUFLR_EN]  = QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN,
 
        [QPHY_DP_PHY_STATUS]            = QSERDES_V5_DP_PHY_STATUS,
+       [QPHY_DP_PHY_VCO_DIV]           = QSERDES_V5_DP_PHY_VCO_DIV,
 
        [QPHY_TX_TX_POL_INV]            = QSERDES_V5_5NM_TX_TX_POL_INV,
        [QPHY_TX_TX_DRV_LVL]            = QSERDES_V5_5NM_TX_TX_DRV_LVL,
@@ -174,6 +178,7 @@ static const unsigned int qmp_v6_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
        [QPHY_COM_BIAS_EN_CLKBUFLR_EN]  = QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN,
 
        [QPHY_DP_PHY_STATUS]            = QSERDES_V6_DP_PHY_STATUS,
+       [QPHY_DP_PHY_VCO_DIV]           = QSERDES_V6_DP_PHY_VCO_DIV,
 
        [QPHY_TX_TX_POL_INV]            = QSERDES_V6_TX_TX_POL_INV,
        [QPHY_TX_TX_DRV_LVL]            = QSERDES_V6_TX_TX_DRV_LVL,
@@ -2150,9 +2155,9 @@ static bool qmp_combo_configure_dp_mode(struct qmp_combo *qmp)
        writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
 
        if (reverse)
-               writel(0x4c, qmp->pcs + QSERDES_DP_PHY_MODE);
+               writel(0x4c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE);
        else
-               writel(0x5c, qmp->pcs + QSERDES_DP_PHY_MODE);
+               writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE);
 
        return reverse;
 }
@@ -2162,6 +2167,7 @@ static int qmp_combo_configure_dp_clocks(struct qmp_combo *qmp)
        const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
        u32 phy_vco_div;
        unsigned long pixel_freq;
+       const struct qmp_phy_cfg *cfg = qmp->cfg;
 
        switch (dp_opts->link_rate) {
        case 1620:
@@ -2184,7 +2190,7 @@ static int qmp_combo_configure_dp_clocks(struct qmp_combo *qmp)
                /* Other link rates aren't supported */
                return -EINVAL;
        }
-       writel(phy_vco_div, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_VCO_DIV);
+       writel(phy_vco_div, qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_VCO_DIV]);
 
        clk_set_rate(qmp->dp_link_hw.clk, dp_opts->link_rate * 100000);
        clk_set_rate(qmp->dp_pixel_hw.clk, pixel_freq);
index f5cfacf9be964ea9068eace03dcd1d9b58e187a2..181057421c113f90c929fa64a12ff85d35c550c9 100644 (file)
@@ -7,6 +7,7 @@
 #define QCOM_PHY_QMP_DP_PHY_V5_H_
 
 /* Only for QMP V5 PHY - DP PHY registers */
+#define QSERDES_V5_DP_PHY_VCO_DIV                      0x070
 #define QSERDES_V5_DP_PHY_AUX_INTERRUPT_STATUS         0x0d8
 #define QSERDES_V5_DP_PHY_STATUS                       0x0dc
 
index 01a20d3be4b812c33fc0869a79601cdc6e89d606..fa967a1af058f7d5c568adf5173f04c6c12127aa 100644 (file)
@@ -7,6 +7,7 @@
 #define QCOM_PHY_QMP_DP_PHY_V6_H_
 
 /* Only for QMP V6 PHY - DP PHY registers */
+#define QSERDES_V6_DP_PHY_VCO_DIV                      0x070
 #define QSERDES_V6_DP_PHY_AUX_INTERRUPT_STATUS         0x0e0
 #define QSERDES_V6_DP_PHY_STATUS                       0x0e4
 
index a34f67bb7e61ad7b23cfc2d510054bb4348b8a36..b60a4b60451e5c1cda026c1565e87e5c5c7f86fe 100644 (file)
@@ -87,6 +87,7 @@ config PHY_ROCKCHIP_SAMSUNG_HDPTX
        tristate "Rockchip Samsung HDMI/eDP Combo PHY driver"
        depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
        select GENERIC_PHY
+       select RATIONAL
        help
          Enable this to support the Rockchip HDMI/eDP Combo PHY
          with Samsung IP block.
index 76b9cf417591de0b7d9f5887dc78b075bd71e6bf..bf74e429ff46e71dccb7da3b6640014e2ba67159 100644 (file)
@@ -125,12 +125,15 @@ struct rockchip_combphy_grfcfg {
 };
 
 struct rockchip_combphy_cfg {
+       unsigned int num_phys;
+       unsigned int phy_ids[3];
        const struct rockchip_combphy_grfcfg *grfcfg;
        int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
 };
 
 struct rockchip_combphy_priv {
        u8 type;
+       int id;
        void __iomem *mmio;
        int num_clks;
        struct clk_bulk_data *clks;
@@ -320,7 +323,7 @@ static int rockchip_combphy_probe(struct platform_device *pdev)
        struct rockchip_combphy_priv *priv;
        const struct rockchip_combphy_cfg *phy_cfg;
        struct resource *res;
-       int ret;
+       int ret, id;
 
        phy_cfg = of_device_get_match_data(dev);
        if (!phy_cfg) {
@@ -338,6 +341,15 @@ static int rockchip_combphy_probe(struct platform_device *pdev)
                return ret;
        }
 
+       /* find the phy-id from the io address */
+       priv->id = -ENODEV;
+       for (id = 0; id < phy_cfg->num_phys; id++) {
+               if (res->start == phy_cfg->phy_ids[id]) {
+                       priv->id = id;
+                       break;
+               }
+       }
+
        priv->dev = dev;
        priv->type = PHY_NONE;
        priv->cfg = phy_cfg;
@@ -562,6 +574,12 @@ static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = {
 };
 
 static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {
+       .num_phys = 3,
+       .phy_ids = {
+               0xfe820000,
+               0xfe830000,
+               0xfe840000,
+       },
        .grfcfg         = &rk3568_combphy_grfcfgs,
        .combphy_cfg    = rk3568_combphy_cfg,
 };
@@ -578,8 +596,14 @@ static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv)
                rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
                rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
                rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
-               rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l0_sel, true);
-               rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l1_sel, true);
+               switch (priv->id) {
+               case 1:
+                       rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l0_sel, true);
+                       break;
+               case 2:
+                       rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l1_sel, true);
+                       break;
+               }
                break;
        case PHY_TYPE_USB3:
                /* Set SSC downward spread spectrum */
@@ -736,6 +760,12 @@ static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = {
 };
 
 static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = {
+       .num_phys = 3,
+       .phy_ids = {
+               0xfee00000,
+               0xfee10000,
+               0xfee20000,
+       },
        .grfcfg         = &rk3588_combphy_grfcfgs,
        .combphy_cfg    = rk3588_combphy_cfg,
 };
index 121e5961ce11472ff1576dc83686072eb2f115e0..9857ee45b89e0de1e26d92ee5a8f748edc34010f 100644 (file)
@@ -40,6 +40,8 @@
 #define RK3588_BIFURCATION_LANE_0_1            BIT(0)
 #define RK3588_BIFURCATION_LANE_2_3            BIT(1)
 #define RK3588_LANE_AGGREGATION                BIT(2)
+#define RK3588_PCIE1LN_SEL_EN                  (GENMASK(1, 0) << 16)
+#define RK3588_PCIE30_PHY_MODE_EN              (GENMASK(2, 0) << 16)
 
 struct rockchip_p3phy_ops;
 
@@ -132,7 +134,7 @@ static const struct rockchip_p3phy_ops rk3568_ops = {
 static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
 {
        u32 reg = 0;
-       u8 mode = 0;
+       u8 mode = RK3588_LANE_AGGREGATION; /* default */
        int ret;
 
        /* Deassert PCIe PMA output clamp mode */
@@ -140,31 +142,24 @@ static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
 
        /* Set bifurcation if needed */
        for (int i = 0; i < priv->num_lanes; i++) {
-               if (!priv->lanes[i])
-                       mode |= (BIT(i) << 3);
-
                if (priv->lanes[i] > 1)
-                       mode |= (BIT(i) >> 1);
-       }
-
-       if (!mode)
-               reg = RK3588_LANE_AGGREGATION;
-       else {
-               if (mode & (BIT(0) | BIT(1)))
-                       reg |= RK3588_BIFURCATION_LANE_0_1;
-
-               if (mode & (BIT(2) | BIT(3)))
-                       reg |= RK3588_BIFURCATION_LANE_2_3;
+                       mode &= ~RK3588_LANE_AGGREGATION;
+               if (priv->lanes[i] == 3)
+                       mode |= RK3588_BIFURCATION_LANE_0_1;
+               if (priv->lanes[i] == 4)
+                       mode |= RK3588_BIFURCATION_LANE_2_3;
        }
 
-       regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, (0x7<<16) | reg);
+       reg = mode;
+       regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0,
+                    RK3588_PCIE30_PHY_MODE_EN | reg);
 
        /* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */
        if (!IS_ERR(priv->pipe_grf)) {
-               reg = (mode & (BIT(6) | BIT(7))) >> 6;
+               reg = mode & (RK3588_BIFURCATION_LANE_0_1 | RK3588_BIFURCATION_LANE_2_3);
                if (reg)
                        regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON,
-                                    (reg << 16) | reg);
+                                    RK3588_PCIE1LN_SEL_EN | reg);
        }
 
        reset_control_deassert(priv->p30phy);
index 13cd614e12a1d3c8ad98de07a40f63091409d228..751fecd466e3e3b5d8bd1faf3071812dd3df3cf2 100644 (file)
@@ -69,7 +69,6 @@ struct tusb1210 {
        struct delayed_work chg_det_work;
        struct notifier_block psy_nb;
        struct power_supply *psy;
-       struct power_supply *charger;
 #endif
 };
 
@@ -236,19 +235,24 @@ static const char * const tusb1210_chargers[] = {
 
 static bool tusb1210_get_online(struct tusb1210 *tusb)
 {
+       struct power_supply *charger = NULL;
        union power_supply_propval val;
-       int i;
+       bool online = false;
+       int i, ret;
 
-       for (i = 0; i < ARRAY_SIZE(tusb1210_chargers) && !tusb->charger; i++)
-               tusb->charger = power_supply_get_by_name(tusb1210_chargers[i]);
+       for (i = 0; i < ARRAY_SIZE(tusb1210_chargers) && !charger; i++)
+               charger = power_supply_get_by_name(tusb1210_chargers[i]);
 
-       if (!tusb->charger)
+       if (!charger)
                return false;
 
-       if (power_supply_get_property(tusb->charger, POWER_SUPPLY_PROP_ONLINE, &val))
-               return false;
+       ret = power_supply_get_property(charger, POWER_SUPPLY_PROP_ONLINE, &val);
+       if (ret == 0)
+               online = val.intval;
+
+       power_supply_put(charger);
 
-       return val.intval;
+       return online;
 }
 
 static void tusb1210_chg_det_work(struct work_struct *work)
@@ -473,9 +477,6 @@ static void tusb1210_remove_charger_detect(struct tusb1210 *tusb)
                cancel_delayed_work_sync(&tusb->chg_det_work);
                power_supply_unregister(tusb->psy);
        }
-
-       if (tusb->charger)
-               power_supply_put(tusb->charger);
 }
 #else
 static void tusb1210_probe_charger_detect(struct tusb1210 *tusb) { }
index d376fa7114d1a024d63eba168a6809f0816acfba..029efe16f8cc29d04942ef4f420c37a25dc2f4b3 100644 (file)
@@ -43,7 +43,7 @@
 #define SCU614         0x614 /* Disable GPIO Internal Pull-Down #1 */
 #define SCU618         0x618 /* Disable GPIO Internal Pull-Down #2 */
 #define SCU61C         0x61c /* Disable GPIO Internal Pull-Down #3 */
-#define SCU620         0x620 /* Disable GPIO Internal Pull-Down #4 */
+#define SCU630         0x630 /* Disable GPIO Internal Pull-Down #4 */
 #define SCU634         0x634 /* Disable GPIO Internal Pull-Down #5 */
 #define SCU638         0x638 /* Disable GPIO Internal Pull-Down #6 */
 #define SCU690         0x690 /* Multi-function Pin Control #24 */
@@ -2495,38 +2495,38 @@ static struct aspeed_pin_config aspeed_g6_configs[] = {
        ASPEED_PULL_DOWN_PINCONF(D14, SCU61C, 0),
 
        /* GPIOS7 */
-       ASPEED_PULL_DOWN_PINCONF(T24, SCU620, 23),
+       ASPEED_PULL_DOWN_PINCONF(T24, SCU630, 23),
        /* GPIOS6 */
-       ASPEED_PULL_DOWN_PINCONF(P23, SCU620, 22),
+       ASPEED_PULL_DOWN_PINCONF(P23, SCU630, 22),
        /* GPIOS5 */
-       ASPEED_PULL_DOWN_PINCONF(P24, SCU620, 21),
+       ASPEED_PULL_DOWN_PINCONF(P24, SCU630, 21),
        /* GPIOS4 */
-       ASPEED_PULL_DOWN_PINCONF(R26, SCU620, 20),
+       ASPEED_PULL_DOWN_PINCONF(R26, SCU630, 20),
        /* GPIOS3*/
-       ASPEED_PULL_DOWN_PINCONF(R24, SCU620, 19),
+       ASPEED_PULL_DOWN_PINCONF(R24, SCU630, 19),
        /* GPIOS2 */
-       ASPEED_PULL_DOWN_PINCONF(T26, SCU620, 18),
+       ASPEED_PULL_DOWN_PINCONF(T26, SCU630, 18),
        /* GPIOS1 */
-       ASPEED_PULL_DOWN_PINCONF(T25, SCU620, 17),
+       ASPEED_PULL_DOWN_PINCONF(T25, SCU630, 17),
        /* GPIOS0 */
-       ASPEED_PULL_DOWN_PINCONF(R23, SCU620, 16),
+       ASPEED_PULL_DOWN_PINCONF(R23, SCU630, 16),
 
        /* GPIOR7 */
-       ASPEED_PULL_DOWN_PINCONF(U26, SCU620, 15),
+       ASPEED_PULL_DOWN_PINCONF(U26, SCU630, 15),
        /* GPIOR6 */
-       ASPEED_PULL_DOWN_PINCONF(W26, SCU620, 14),
+       ASPEED_PULL_DOWN_PINCONF(W26, SCU630, 14),
        /* GPIOR5 */
-       ASPEED_PULL_DOWN_PINCONF(T23, SCU620, 13),
+       ASPEED_PULL_DOWN_PINCONF(T23, SCU630, 13),
        /* GPIOR4 */
-       ASPEED_PULL_DOWN_PINCONF(U25, SCU620, 12),
+       ASPEED_PULL_DOWN_PINCONF(U25, SCU630, 12),
        /* GPIOR3*/
-       ASPEED_PULL_DOWN_PINCONF(V26, SCU620, 11),
+       ASPEED_PULL_DOWN_PINCONF(V26, SCU630, 11),
        /* GPIOR2 */
-       ASPEED_PULL_DOWN_PINCONF(V24, SCU620, 10),
+       ASPEED_PULL_DOWN_PINCONF(V24, SCU630, 10),
        /* GPIOR1 */
-       ASPEED_PULL_DOWN_PINCONF(U24, SCU620, 9),
+       ASPEED_PULL_DOWN_PINCONF(U24, SCU630, 9),
        /* GPIOR0 */
-       ASPEED_PULL_DOWN_PINCONF(V25, SCU620, 8),
+       ASPEED_PULL_DOWN_PINCONF(V25, SCU630, 8),
 
        /* GPIOX7 */
        ASPEED_PULL_DOWN_PINCONF(AB10, SCU634, 31),
index 6649357637ff337dc49c4e522287d2366dc36516..cffeb869130ddab486fb2ce00e4c1d5a27575875 100644 (file)
@@ -2124,13 +2124,7 @@ int pinctrl_enable(struct pinctrl_dev *pctldev)
 
        error = pinctrl_claim_hogs(pctldev);
        if (error) {
-               dev_err(pctldev->dev, "could not claim hogs: %i\n",
-                       error);
-               pinctrl_free_pindescs(pctldev, pctldev->desc->pins,
-                                     pctldev->desc->npins);
-               mutex_destroy(&pctldev->mutex);
-               kfree(pctldev);
-
+               dev_err(pctldev->dev, "could not claim hogs: %i\n", error);
                return error;
        }
 
index df1efc2e5202591d5f9f23d95f6008853b91e046..6a94ecd6a8deaeb6b7fc14c6387987f52ead306a 100644 (file)
@@ -220,14 +220,16 @@ int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev)
        for (state = 0; ; state++) {
                /* Retrieve the pinctrl-* property */
                propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);
-               if (!propname)
-                       return -ENOMEM;
+               if (!propname) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
                prop = of_find_property(np, propname, &size);
                kfree(propname);
                if (!prop) {
                        if (state == 0) {
-                               of_node_put(np);
-                               return -ENODEV;
+                               ret = -ENODEV;
+                               goto err;
                        }
                        break;
                }
index ac97724c59bae9705e89c93246ec3f09580d663d..4e87f5b875c0e8f7089b9411c9b1610eaa2a8b9a 100644 (file)
@@ -231,6 +231,7 @@ static const unsigned int byt_score_pins_map[BYT_NGPIO_SCORE] = {
 /* SCORE groups */
 static const unsigned int byt_score_uart1_pins[] = { 70, 71, 72, 73 };
 static const unsigned int byt_score_uart2_pins[] = { 74, 75, 76, 77 };
+static const unsigned int byt_score_uart3_pins[] = { 57, 61 };
 
 static const unsigned int byt_score_pwm0_pins[] = { 94 };
 static const unsigned int byt_score_pwm1_pins[] = { 95 };
@@ -278,37 +279,38 @@ static const unsigned int byt_score_plt_clk5_pins[] = { 101 };
 static const unsigned int byt_score_smbus_pins[] = { 51, 52, 53 };
 
 static const struct intel_pingroup byt_score_groups[] = {
-       PIN_GROUP("uart1_grp", byt_score_uart1_pins, 1),
-       PIN_GROUP("uart2_grp", byt_score_uart2_pins, 1),
-       PIN_GROUP("pwm0_grp", byt_score_pwm0_pins, 1),
-       PIN_GROUP("pwm1_grp", byt_score_pwm1_pins, 1),
-       PIN_GROUP("ssp2_grp", byt_score_ssp2_pins, 1),
-       PIN_GROUP("sio_spi_grp", byt_score_sio_spi_pins, 1),
-       PIN_GROUP("i2c5_grp", byt_score_i2c5_pins, 1),
-       PIN_GROUP("i2c6_grp", byt_score_i2c6_pins, 1),
-       PIN_GROUP("i2c4_grp", byt_score_i2c4_pins, 1),
-       PIN_GROUP("i2c3_grp", byt_score_i2c3_pins, 1),
-       PIN_GROUP("i2c2_grp", byt_score_i2c2_pins, 1),
-       PIN_GROUP("i2c1_grp", byt_score_i2c1_pins, 1),
-       PIN_GROUP("i2c0_grp", byt_score_i2c0_pins, 1),
-       PIN_GROUP("ssp0_grp", byt_score_ssp0_pins, 1),
-       PIN_GROUP("ssp1_grp", byt_score_ssp1_pins, 1),
-       PIN_GROUP("sdcard_grp", byt_score_sdcard_pins, byt_score_sdcard_mux_values),
-       PIN_GROUP("sdio_grp", byt_score_sdio_pins, 1),
-       PIN_GROUP("emmc_grp", byt_score_emmc_pins, 1),
-       PIN_GROUP("lpc_grp", byt_score_ilb_lpc_pins, 1),
-       PIN_GROUP("sata_grp", byt_score_sata_pins, 1),
-       PIN_GROUP("plt_clk0_grp", byt_score_plt_clk0_pins, 1),
-       PIN_GROUP("plt_clk1_grp", byt_score_plt_clk1_pins, 1),
-       PIN_GROUP("plt_clk2_grp", byt_score_plt_clk2_pins, 1),
-       PIN_GROUP("plt_clk3_grp", byt_score_plt_clk3_pins, 1),
-       PIN_GROUP("plt_clk4_grp", byt_score_plt_clk4_pins, 1),
-       PIN_GROUP("plt_clk5_grp", byt_score_plt_clk5_pins, 1),
-       PIN_GROUP("smbus_grp", byt_score_smbus_pins, 1),
+       PIN_GROUP_GPIO("uart1_grp", byt_score_uart1_pins, 1),
+       PIN_GROUP_GPIO("uart2_grp", byt_score_uart2_pins, 1),
+       PIN_GROUP_GPIO("uart3_grp", byt_score_uart3_pins, 1),
+       PIN_GROUP_GPIO("pwm0_grp", byt_score_pwm0_pins, 1),
+       PIN_GROUP_GPIO("pwm1_grp", byt_score_pwm1_pins, 1),
+       PIN_GROUP_GPIO("ssp2_grp", byt_score_ssp2_pins, 1),
+       PIN_GROUP_GPIO("sio_spi_grp", byt_score_sio_spi_pins, 1),
+       PIN_GROUP_GPIO("i2c5_grp", byt_score_i2c5_pins, 1),
+       PIN_GROUP_GPIO("i2c6_grp", byt_score_i2c6_pins, 1),
+       PIN_GROUP_GPIO("i2c4_grp", byt_score_i2c4_pins, 1),
+       PIN_GROUP_GPIO("i2c3_grp", byt_score_i2c3_pins, 1),
+       PIN_GROUP_GPIO("i2c2_grp", byt_score_i2c2_pins, 1),
+       PIN_GROUP_GPIO("i2c1_grp", byt_score_i2c1_pins, 1),
+       PIN_GROUP_GPIO("i2c0_grp", byt_score_i2c0_pins, 1),
+       PIN_GROUP_GPIO("ssp0_grp", byt_score_ssp0_pins, 1),
+       PIN_GROUP_GPIO("ssp1_grp", byt_score_ssp1_pins, 1),
+       PIN_GROUP_GPIO("sdcard_grp", byt_score_sdcard_pins, byt_score_sdcard_mux_values),
+       PIN_GROUP_GPIO("sdio_grp", byt_score_sdio_pins, 1),
+       PIN_GROUP_GPIO("emmc_grp", byt_score_emmc_pins, 1),
+       PIN_GROUP_GPIO("lpc_grp", byt_score_ilb_lpc_pins, 1),
+       PIN_GROUP_GPIO("sata_grp", byt_score_sata_pins, 1),
+       PIN_GROUP_GPIO("plt_clk0_grp", byt_score_plt_clk0_pins, 1),
+       PIN_GROUP_GPIO("plt_clk1_grp", byt_score_plt_clk1_pins, 1),
+       PIN_GROUP_GPIO("plt_clk2_grp", byt_score_plt_clk2_pins, 1),
+       PIN_GROUP_GPIO("plt_clk3_grp", byt_score_plt_clk3_pins, 1),
+       PIN_GROUP_GPIO("plt_clk4_grp", byt_score_plt_clk4_pins, 1),
+       PIN_GROUP_GPIO("plt_clk5_grp", byt_score_plt_clk5_pins, 1),
+       PIN_GROUP_GPIO("smbus_grp", byt_score_smbus_pins, 1),
 };
 
 static const char * const byt_score_uart_groups[] = {
-       "uart1_grp", "uart2_grp",
+       "uart1_grp", "uart2_grp", "uart3_grp",
 };
 static const char * const byt_score_pwm_groups[] = {
        "pwm0_grp", "pwm1_grp",
@@ -332,12 +334,14 @@ static const char * const byt_score_plt_clk_groups[] = {
 };
 static const char * const byt_score_smbus_groups[] = { "smbus_grp" };
 static const char * const byt_score_gpio_groups[] = {
-       "uart1_grp", "uart2_grp", "pwm0_grp", "pwm1_grp", "ssp0_grp",
-       "ssp1_grp", "ssp2_grp", "sio_spi_grp", "i2c0_grp", "i2c1_grp",
-       "i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp", "i2c6_grp",
-       "sdcard_grp", "sdio_grp", "emmc_grp", "lpc_grp", "sata_grp",
-       "plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
-       "plt_clk4_grp", "plt_clk5_grp", "smbus_grp",
+       "uart1_grp_gpio", "uart2_grp_gpio", "uart3_grp_gpio", "pwm0_grp_gpio",
+       "pwm1_grp_gpio", "ssp0_grp_gpio", "ssp1_grp_gpio", "ssp2_grp_gpio",
+       "sio_spi_grp_gpio", "i2c0_grp_gpio", "i2c1_grp_gpio", "i2c2_grp_gpio",
+       "i2c3_grp_gpio", "i2c4_grp_gpio", "i2c5_grp_gpio", "i2c6_grp_gpio",
+       "sdcard_grp_gpio", "sdio_grp_gpio", "emmc_grp_gpio", "lpc_grp_gpio",
+       "sata_grp_gpio", "plt_clk0_grp_gpio", "plt_clk1_grp_gpio",
+       "plt_clk2_grp_gpio", "plt_clk3_grp_gpio", "plt_clk4_grp_gpio",
+       "plt_clk5_grp_gpio", "smbus_grp_gpio",
 };
 
 static const struct intel_function byt_score_functions[] = {
@@ -456,8 +460,8 @@ static const struct intel_pingroup byt_sus_groups[] = {
        PIN_GROUP("usb_oc_grp_gpio", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_gpio_mode_values),
        PIN_GROUP("usb_ulpi_grp_gpio", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_gpio_mode_values),
        PIN_GROUP("pcu_spi_grp_gpio", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_gpio_mode_values),
-       PIN_GROUP("pmu_clk1_grp", byt_sus_pmu_clk1_pins, 1),
-       PIN_GROUP("pmu_clk2_grp", byt_sus_pmu_clk2_pins, 1),
+       PIN_GROUP_GPIO("pmu_clk1_grp", byt_sus_pmu_clk1_pins, 1),
+       PIN_GROUP_GPIO("pmu_clk2_grp", byt_sus_pmu_clk2_pins, 1),
 };
 
 static const char * const byt_sus_usb_groups[] = {
@@ -469,7 +473,7 @@ static const char * const byt_sus_pmu_clk_groups[] = {
 };
 static const char * const byt_sus_gpio_groups[] = {
        "usb_oc_grp_gpio", "usb_ulpi_grp_gpio", "pcu_spi_grp_gpio",
-       "pmu_clk1_grp", "pmu_clk2_grp",
+       "pmu_clk1_grp_gpio", "pmu_clk2_grp_gpio",
 };
 
 static const struct intel_function byt_sus_functions[] = {
index fde65e18cd145ecb1eb809f87ecec289067e44e8..6981e2fab93f34998b737ac39446c4eed5646923 100644 (file)
@@ -179,6 +179,10 @@ struct intel_community {
                .modes = __builtin_choose_expr(__builtin_constant_p((m)), NULL, (m)),   \
        }
 
+#define PIN_GROUP_GPIO(n, p, m)                                                \
+        PIN_GROUP(n, p, m),                                            \
+        PIN_GROUP(n "_gpio", p, 0)
+
 #define FUNCTION(n, g)                                                 \
        {                                                               \
                .func = PINCTRL_PINFUNCTION((n), (g), ARRAY_SIZE(g)),   \
index b6bc31abd2b068695dcfd5025c0f31ea0b3c679e..b19bc391705ee079939f34ab03d554160d97c234 100644 (file)
@@ -165,20 +165,21 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
                err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &ret);
                break;
        case PIN_CONFIG_INPUT_ENABLE:
-       case PIN_CONFIG_OUTPUT_ENABLE:
+               err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_IES, &ret);
+               if (!ret)
+                       err = -EINVAL;
+               break;
+       case PIN_CONFIG_OUTPUT:
                err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret);
                if (err)
                        break;
-               /*     CONFIG     Current direction return value
-                * -------------  ----------------- ----------------------
-                * OUTPUT_ENABLE       output       1 (= HW value)
-                *                     input        0 (= HW value)
-                * INPUT_ENABLE        output       0 (= reverse HW value)
-                *                     input        1 (= reverse HW value)
-                */
-               if (param == PIN_CONFIG_INPUT_ENABLE)
-                       ret = !ret;
 
+               if (!ret) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DO, &ret);
                break;
        case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
                err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret);
@@ -193,6 +194,8 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
                }
 
                err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &ret);
+               if (!ret)
+                       err = -EINVAL;
                break;
        case PIN_CONFIG_DRIVE_STRENGTH:
                if (!hw->soc->drive_get)
@@ -281,26 +284,9 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
                        break;
                err = hw->soc->bias_set_combo(hw, desc, 0, arg);
                break;
-       case PIN_CONFIG_OUTPUT_ENABLE:
-               err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
-                                      MTK_DISABLE);
-               /* Keep set direction to consider the case that a GPIO pin
-                *  does not have SMT control
-                */
-               if (err != -ENOTSUPP)
-                       break;
-
-               err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
-                                      MTK_OUTPUT);
-               break;
        case PIN_CONFIG_INPUT_ENABLE:
                /* regard all non-zero value as enable */
                err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, !!arg);
-               if (err)
-                       break;
-
-               err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
-                                      MTK_INPUT);
                break;
        case PIN_CONFIG_SLEW_RATE:
                /* regard all non-zero value as enable */
index 79f5d753d7e1a53df0da9bb0446bf8fdfbd3042c..50a87d9618a8e8e078424db33c7e13a7c7ed1dc6 100644 (file)
@@ -250,7 +250,7 @@ static const unsigned int pdm_dclk_x_pins[]         = { GPIOX_10 };
 static const unsigned int pdm_din2_a_pins[]            = { GPIOA_6 };
 static const unsigned int pdm_din1_a_pins[]            = { GPIOA_7 };
 static const unsigned int pdm_din0_a_pins[]            = { GPIOA_8 };
-static const unsigned int pdm_dclk_pins[]              = { GPIOA_9 };
+static const unsigned int pdm_dclk_a_pins[]            = { GPIOA_9 };
 
 /* gen_clk */
 static const unsigned int gen_clk_x_pins[]             = { GPIOX_7 };
@@ -591,7 +591,7 @@ static struct meson_pmx_group meson_a1_periphs_groups[] = {
        GROUP(pdm_din2_a,               3),
        GROUP(pdm_din1_a,               3),
        GROUP(pdm_din0_a,               3),
-       GROUP(pdm_dclk,                 3),
+       GROUP(pdm_dclk_a,               3),
        GROUP(pwm_c_a,                  3),
        GROUP(pwm_b_a,                  3),
 
@@ -755,7 +755,7 @@ static const char * const spi_a_groups[] = {
 
 static const char * const pdm_groups[] = {
        "pdm_din0_x", "pdm_din1_x", "pdm_din2_x", "pdm_dclk_x", "pdm_din2_a",
-       "pdm_din1_a", "pdm_din0_a", "pdm_dclk",
+       "pdm_din1_a", "pdm_din0_a", "pdm_dclk_a",
 };
 
 static const char * const gen_clk_groups[] = {
index eb5a8c65426061fec78bced9cf66243debbb561f..20425afc6b331b336c314d5a3f4c6dc9b813382d 100644 (file)
@@ -2045,7 +2045,9 @@ static void rzg2l_gpio_irq_restore(struct rzg2l_pinctrl *pctrl)
 
        for (unsigned int i = 0; i < RZG2L_TINT_MAX_INTERRUPT; i++) {
                struct irq_data *data;
+               unsigned long flags;
                unsigned int virq;
+               int ret;
 
                if (!pctrl->hwirq[i])
                        continue;
@@ -2063,8 +2065,18 @@ static void rzg2l_gpio_irq_restore(struct rzg2l_pinctrl *pctrl)
                        continue;
                }
 
-               if (!irqd_irq_disabled(data))
+               /*
+                * This has to be atomically executed to protect against a concurrent
+                * interrupt.
+                */
+               raw_spin_lock_irqsave(&pctrl->lock.rlock, flags);
+               ret = rzg2l_gpio_irq_set_type(data, irqd_get_trigger_type(data));
+               if (!ret && !irqd_irq_disabled(data))
                        rzg2l_gpio_irq_enable(data);
+               raw_spin_unlock_irqrestore(&pctrl->lock.rlock, flags);
+
+               if (ret)
+                       dev_crit(pctrl->dev, "Failed to set IRQ type for virq=%u\n", virq);
        }
 }
 
index b456370166b6bb2158ca0916e0eb9e106f9fd9d7..b4f49720c87f62aa6e8349af12797382f740c2b7 100644 (file)
@@ -208,6 +208,15 @@ static const struct dmi_system_id fwbug_list[] = {
                        DMI_MATCH(DMI_BIOS_VERSION, "03.03"),
                }
        },
+       {
+               .ident = "Framework Laptop 13 (Phoenix)",
+               .driver_data = &quirk_spurious_8042,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Laptop 13 (AMD Ryzen 7040Series)"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "03.05"),
+               }
+       },
        {}
 };
 
index 6b26e48ce8ad2a5f4de6e78751ffec8941610336..7d6079b02589cbacbb203bdc42cfac4e42dd601c 100644 (file)
@@ -7,4 +7,4 @@
 obj-$(CONFIG_AMD_PMF) += amd-pmf.o
 amd-pmf-objs := core.o acpi.o sps.o \
                auto-mode.o cnqf.o \
-               tee-if.o spc.o
+               tee-if.o spc.o pmf-quirks.o
index d0cf46e2fc8e8a073149c61c52b27e9cc9051da6..1157ec148880b54ec145a7ed9353a656e36f0b33 100644 (file)
@@ -343,7 +343,10 @@ static int apmf_if_verify_interface(struct amd_pmf_dev *pdev)
        if (err)
                return err;
 
-       pdev->supported_func = output.supported_functions;
+       /* only set if not already set by a quirk */
+       if (!pdev->supported_func)
+               pdev->supported_func = output.supported_functions;
+
        dev_dbg(pdev->dev, "supported functions:0x%x notifications:0x%x version:%u\n",
                output.supported_functions, output.notification_mask, output.version);
 
@@ -437,7 +440,7 @@ int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev)
 
        status = acpi_walk_resources(ahandle, METHOD_NAME__CRS, apmf_walk_resources, pmf_dev);
        if (ACPI_FAILURE(status)) {
-               dev_err(pmf_dev->dev, "acpi_walk_resources failed :%d\n", status);
+               dev_dbg(pmf_dev->dev, "acpi_walk_resources failed :%d\n", status);
                return -EINVAL;
        }
 
index 5d4f80698a8b8824bdb59b4e5632ca5f05982c48..64e6e34a2a9acd954f4ce9a916f77673193aba06 100644 (file)
@@ -445,6 +445,7 @@ static int amd_pmf_probe(struct platform_device *pdev)
        mutex_init(&dev->lock);
        mutex_init(&dev->update_mutex);
 
+       amd_pmf_quirks_init(dev);
        apmf_acpi_init(dev);
        platform_set_drvdata(pdev, dev);
        amd_pmf_dbgfs_register(dev);
diff --git a/drivers/platform/x86/amd/pmf/pmf-quirks.c b/drivers/platform/x86/amd/pmf/pmf-quirks.c
new file mode 100644 (file)
index 0000000..0b2eb0a
--- /dev/null
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * AMD Platform Management Framework Driver Quirks
+ *
+ * Copyright (c) 2024, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Mario Limonciello <mario.limonciello@amd.com>
+ */
+
+#include <linux/dmi.h>
+
+#include "pmf.h"
+
+struct quirk_entry {
+       u32 supported_func;
+};
+
+static struct quirk_entry quirk_no_sps_bug = {
+       .supported_func = 0x4003,
+};
+
+static const struct dmi_system_id fwbug_list[] = {
+       {
+               .ident = "ROG Zephyrus G14",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "GA403UV"),
+               },
+               .driver_data = &quirk_no_sps_bug,
+       },
+       {}
+};
+
+void amd_pmf_quirks_init(struct amd_pmf_dev *dev)
+{
+       const struct dmi_system_id *dmi_id;
+       struct quirk_entry *quirks;
+
+       dmi_id = dmi_first_match(fwbug_list);
+       if (!dmi_id)
+               return;
+
+       quirks = dmi_id->driver_data;
+       if (quirks->supported_func) {
+               dev->supported_func = quirks->supported_func;
+               pr_info("Using supported funcs quirk to avoid %s platform firmware bug\n",
+                       dmi_id->ident);
+       }
+}
+
index 8c4df5753f40d48fefc05c6373a64d0a00469149..eeedd0c0395a89704ce360a6aff9f827566b17b2 100644 (file)
@@ -720,4 +720,7 @@ int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev);
 void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
 void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
 
+/* Quirk infrastructure */
+void amd_pmf_quirks_init(struct amd_pmf_dev *dev);
+
 #endif /* PMF_H */
index 08df9494603c5e2acf152aacfe13fce81a18dc2c..1accdaaf282c5331495e51a6bd71a9203a7c0200 100644 (file)
@@ -719,7 +719,9 @@ static struct miscdevice isst_if_char_driver = {
 };
 
 static const struct x86_cpu_id hpm_cpu_ids[] = {
+       X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_D,     NULL),
        X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_X,     NULL),
+       X86_MATCH_INTEL_FAM6_MODEL(ATOM_CRESTMONT,      NULL),
        X86_MATCH_INTEL_FAM6_MODEL(ATOM_CRESTMONT_X,    NULL),
        {}
 };
index bd75d61ff8a66196d620b5ca2824d8bb16332237..ef730200a04bd94682c781be092a43f15f88190e 100644 (file)
@@ -29,7 +29,7 @@
 #include "uncore-frequency-common.h"
 
 #define        UNCORE_MAJOR_VERSION            0
-#define        UNCORE_MINOR_VERSION            1
+#define        UNCORE_MINOR_VERSION            2
 #define UNCORE_HEADER_INDEX            0
 #define UNCORE_FABRIC_CLUSTER_OFFSET   8
 
@@ -329,7 +329,7 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_
                        goto remove_clusters;
                }
 
-               if (TPMI_MINOR_VERSION(pd_info->ufs_header_ver) != UNCORE_MINOR_VERSION)
+               if (TPMI_MINOR_VERSION(pd_info->ufs_header_ver) > UNCORE_MINOR_VERSION)
                        dev_info(&auxdev->dev, "Uncore: Ignore: Unsupported minor version:%lx\n",
                                 TPMI_MINOR_VERSION(pd_info->ufs_header_ver));
 
index 1305cba61edd4b957313d7d86fb05158975b3086..aca123783efccdcb73391214d20c3722975222ca 100644 (file)
@@ -588,7 +588,7 @@ static const struct regulator_ops mt6360_chg_otg_ops = {
 };
 
 static const struct regulator_desc mt6360_otg_rdesc = {
-       .of_match = "usb-otg-vbus",
+       .of_match = "usb-otg-vbus-regulator",
        .name = "usb-otg-vbus",
        .ops = &mt6360_chg_otg_ops,
        .owner = THIS_MODULE,
index c345a77f9f78c0a4a03f5a13a7151901b9945a03..e4dbacd50a437df3562b04d485ec38e11a89b216 100644 (file)
@@ -192,6 +192,7 @@ static const int rt9455_voreg_values[] = {
        4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000
 };
 
+#if IS_ENABLED(CONFIG_USB_PHY)
 /*
  * When the charger is in boost mode, REG02[7:2] represent boost output
  * voltage.
@@ -207,6 +208,7 @@ static const int rt9455_boost_voltage_values[] = {
        5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000,
        5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000,
 };
+#endif
 
 /* REG07[3:0] (VMREG) in uV */
 static const int rt9455_vmreg_values[] = {
index 043736972cb9216c59a7cb3bc6682e056cdb2373..c8425493b95d855a7562406501b7c803ef481b22 100644 (file)
@@ -172,7 +172,6 @@ struct pwm_chip *dwc_pwm_alloc(struct device *dev)
        dwc->clk_ns = 10;
        chip->ops = &dwc_pwm_ops;
 
-       dev_set_drvdata(dev, chip);
        return chip;
 }
 EXPORT_SYMBOL_GPL(dwc_pwm_alloc);
index 676eaf8d7a53f76672527c1871a306cbcdb9b7ba..fb3eadf6fbc464773b17c30235c51f5a4ff6917f 100644 (file)
@@ -31,26 +31,34 @@ static const struct dwc_pwm_info ehl_pwm_info = {
        .size = 0x1000,
 };
 
-static int dwc_pwm_init_one(struct device *dev, void __iomem *base, unsigned int offset)
+static int dwc_pwm_init_one(struct device *dev, struct dwc_pwm_drvdata *ddata, unsigned int idx)
 {
        struct pwm_chip *chip;
        struct dwc_pwm *dwc;
+       int ret;
 
        chip = dwc_pwm_alloc(dev);
        if (IS_ERR(chip))
                return PTR_ERR(chip);
 
        dwc = to_dwc_pwm(chip);
-       dwc->base = base + offset;
+       dwc->base = ddata->io_base + (ddata->info->size * idx);
 
-       return devm_pwmchip_add(dev, chip);
+       ret = devm_pwmchip_add(dev, chip);
+       if (ret)
+               return ret;
+
+       ddata->chips[idx] = chip;
+       return 0;
 }
 
 static int dwc_pwm_probe(struct pci_dev *pci, const struct pci_device_id *id)
 {
        const struct dwc_pwm_info *info;
        struct device *dev = &pci->dev;
-       int i, ret;
+       struct dwc_pwm_drvdata *ddata;
+       unsigned int idx;
+       int ret;
 
        ret = pcim_enable_device(pci);
        if (ret)
@@ -63,17 +71,25 @@ static int dwc_pwm_probe(struct pci_dev *pci, const struct pci_device_id *id)
                return dev_err_probe(dev, ret, "Failed to iomap PCI BAR\n");
 
        info = (const struct dwc_pwm_info *)id->driver_data;
-
-       for (i = 0; i < info->nr; i++) {
-               /*
-                * No need to check for pcim_iomap_table() failure,
-                * pcim_iomap_regions() already does it for us.
-                */
-               ret = dwc_pwm_init_one(dev, pcim_iomap_table(pci)[0], i * info->size);
+       ddata = devm_kzalloc(dev, struct_size(ddata, chips, info->nr), GFP_KERNEL);
+       if (!ddata)
+               return -ENOMEM;
+
+       /*
+        * No need to check for pcim_iomap_table() failure,
+        * pcim_iomap_regions() already does it for us.
+        */
+       ddata->io_base = pcim_iomap_table(pci)[0];
+       ddata->info = info;
+
+       for (idx = 0; idx < ddata->info->nr; idx++) {
+               ret = dwc_pwm_init_one(dev, ddata, idx);
                if (ret)
                        return ret;
        }
 
+       dev_set_drvdata(dev, ddata);
+
        pm_runtime_put(dev);
        pm_runtime_allow(dev);
 
@@ -88,19 +104,24 @@ static void dwc_pwm_remove(struct pci_dev *pci)
 
 static int dwc_pwm_suspend(struct device *dev)
 {
-       struct pwm_chip *chip = dev_get_drvdata(dev);
-       struct dwc_pwm *dwc = to_dwc_pwm(chip);
-       int i;
-
-       for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
-               if (chip->pwms[i].state.enabled) {
-                       dev_err(dev, "PWM %u in use by consumer (%s)\n",
-                               i, chip->pwms[i].label);
-                       return -EBUSY;
+       struct dwc_pwm_drvdata *ddata = dev_get_drvdata(dev);
+       unsigned int idx;
+
+       for (idx = 0; idx < ddata->info->nr; idx++) {
+               struct pwm_chip *chip = ddata->chips[idx];
+               struct dwc_pwm *dwc = to_dwc_pwm(chip);
+               unsigned int i;
+
+               for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
+                       if (chip->pwms[i].state.enabled) {
+                               dev_err(dev, "PWM %u in use by consumer (%s)\n",
+                                       i, chip->pwms[i].label);
+                               return -EBUSY;
+                       }
+                       dwc->ctx[i].cnt = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(i));
+                       dwc->ctx[i].cnt2 = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(i));
+                       dwc->ctx[i].ctrl = dwc_pwm_readl(dwc, DWC_TIM_CTRL(i));
                }
-               dwc->ctx[i].cnt = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(i));
-               dwc->ctx[i].cnt2 = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(i));
-               dwc->ctx[i].ctrl = dwc_pwm_readl(dwc, DWC_TIM_CTRL(i));
        }
 
        return 0;
@@ -108,14 +129,19 @@ static int dwc_pwm_suspend(struct device *dev)
 
 static int dwc_pwm_resume(struct device *dev)
 {
-       struct pwm_chip *chip = dev_get_drvdata(dev);
-       struct dwc_pwm *dwc = to_dwc_pwm(chip);
-       int i;
-
-       for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
-               dwc_pwm_writel(dwc, dwc->ctx[i].cnt, DWC_TIM_LD_CNT(i));
-               dwc_pwm_writel(dwc, dwc->ctx[i].cnt2, DWC_TIM_LD_CNT2(i));
-               dwc_pwm_writel(dwc, dwc->ctx[i].ctrl, DWC_TIM_CTRL(i));
+       struct dwc_pwm_drvdata *ddata = dev_get_drvdata(dev);
+       unsigned int idx;
+
+       for (idx = 0; idx < ddata->info->nr; idx++) {
+               struct pwm_chip *chip = ddata->chips[idx];
+               struct dwc_pwm *dwc = to_dwc_pwm(chip);
+               unsigned int i;
+
+               for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
+                       dwc_pwm_writel(dwc, dwc->ctx[i].cnt, DWC_TIM_LD_CNT(i));
+                       dwc_pwm_writel(dwc, dwc->ctx[i].cnt2, DWC_TIM_LD_CNT2(i));
+                       dwc_pwm_writel(dwc, dwc->ctx[i].ctrl, DWC_TIM_CTRL(i));
+               }
        }
 
        return 0;
index a8b074841ae8054a5a3737127442a1d0e9979e02..c6e2df5a61227131c50fc3c6351326217371c3a3 100644 (file)
@@ -38,6 +38,12 @@ struct dwc_pwm_info {
        unsigned int size;
 };
 
+struct dwc_pwm_drvdata {
+       const struct dwc_pwm_info *info;
+       void __iomem *io_base;
+       struct pwm_chip *chips[];
+};
+
 struct dwc_pwm_ctx {
        u32 cnt;
        u32 cnt2;
index fe7ae0f3f46af985a87f4a0b5c33c3fd09f6b1a8..5ab1a0befe12f791389911651d8548fb3611b6f8 100644 (file)
@@ -352,6 +352,9 @@ void *regulator_irq_helper(struct device *dev,
 
        h->irq = irq;
        h->desc = *d;
+       h->desc.name = devm_kstrdup(dev, d->name, GFP_KERNEL);
+       if (!h->desc.name)
+               return ERR_PTR(-ENOMEM);
 
        ret = init_rdev_state(dev, h, rdev, common_errs, per_rdev_errs,
                              rdev_amount);
index ad6587a378d09cc52515475f96512ed5627880be..24cc9fc94e900a43a8bfa8c30c364cedb2b0b948 100644 (file)
@@ -319,15 +319,15 @@ static unsigned int mt6360_regulator_of_map_mode(unsigned int hw_mode)
        }
 }
 
-#define MT6360_REGULATOR_DESC(_name, _sname, ereg, emask, vreg,        vmask,  \
-                             mreg, mmask, streg, stmask, vranges,      \
-                             vcnts, offon_delay, irq_tbls)             \
+#define MT6360_REGULATOR_DESC(match, _name, _sname, ereg, emask, vreg, \
+                             vmask, mreg, mmask, streg, stmask,        \
+                             vranges, vcnts, offon_delay, irq_tbls)    \
 {                                                                      \
        .desc = {                                                       \
                .name = #_name,                                         \
                .supply_name = #_sname,                                 \
                .id =  MT6360_REGULATOR_##_name,                        \
-               .of_match = of_match_ptr(#_name),                       \
+               .of_match = of_match_ptr(match),                        \
                .regulators_node = of_match_ptr("regulator"),           \
                .of_map_mode = mt6360_regulator_of_map_mode,            \
                .owner = THIS_MODULE,                                   \
@@ -351,21 +351,29 @@ static unsigned int mt6360_regulator_of_map_mode(unsigned int hw_mode)
 }
 
 static const struct mt6360_regulator_desc mt6360_regulator_descs[] =  {
-       MT6360_REGULATOR_DESC(BUCK1, BUCK1_VIN, 0x117, 0x40, 0x110, 0xff, 0x117, 0x30, 0x117, 0x04,
+       MT6360_REGULATOR_DESC("buck1", BUCK1, BUCK1_VIN,
+                             0x117, 0x40, 0x110, 0xff, 0x117, 0x30, 0x117, 0x04,
                              buck_vout_ranges, 256, 0, buck1_irq_tbls),
-       MT6360_REGULATOR_DESC(BUCK2, BUCK2_VIN, 0x127, 0x40, 0x120, 0xff, 0x127, 0x30, 0x127, 0x04,
+       MT6360_REGULATOR_DESC("buck2", BUCK2, BUCK2_VIN,
+                             0x127, 0x40, 0x120, 0xff, 0x127, 0x30, 0x127, 0x04,
                              buck_vout_ranges, 256, 0, buck2_irq_tbls),
-       MT6360_REGULATOR_DESC(LDO6, LDO_VIN3, 0x137, 0x40, 0x13B, 0xff, 0x137, 0x30, 0x137, 0x04,
+       MT6360_REGULATOR_DESC("ldo6", LDO6, LDO_VIN3,
+                             0x137, 0x40, 0x13B, 0xff, 0x137, 0x30, 0x137, 0x04,
                              ldo_vout_ranges1, 256, 0, ldo6_irq_tbls),
-       MT6360_REGULATOR_DESC(LDO7, LDO_VIN3, 0x131, 0x40, 0x135, 0xff, 0x131, 0x30, 0x131, 0x04,
+       MT6360_REGULATOR_DESC("ldo7", LDO7, LDO_VIN3,
+                             0x131, 0x40, 0x135, 0xff, 0x131, 0x30, 0x131, 0x04,
                              ldo_vout_ranges1, 256, 0, ldo7_irq_tbls),
-       MT6360_REGULATOR_DESC(LDO1, LDO_VIN1, 0x217, 0x40, 0x21B, 0xff, 0x217, 0x30, 0x217, 0x04,
+       MT6360_REGULATOR_DESC("ldo1", LDO1, LDO_VIN1,
+                             0x217, 0x40, 0x21B, 0xff, 0x217, 0x30, 0x217, 0x04,
                              ldo_vout_ranges2, 256, 0, ldo1_irq_tbls),
-       MT6360_REGULATOR_DESC(LDO2, LDO_VIN1, 0x211, 0x40, 0x215, 0xff, 0x211, 0x30, 0x211, 0x04,
+       MT6360_REGULATOR_DESC("ldo2", LDO2, LDO_VIN1,
+                             0x211, 0x40, 0x215, 0xff, 0x211, 0x30, 0x211, 0x04,
                              ldo_vout_ranges2, 256, 0, ldo2_irq_tbls),
-       MT6360_REGULATOR_DESC(LDO3, LDO_VIN1, 0x205, 0x40, 0x209, 0xff, 0x205, 0x30, 0x205, 0x04,
+       MT6360_REGULATOR_DESC("ldo3", LDO3, LDO_VIN1,
+                             0x205, 0x40, 0x209, 0xff, 0x205, 0x30, 0x205, 0x04,
                              ldo_vout_ranges2, 256, 100, ldo3_irq_tbls),
-       MT6360_REGULATOR_DESC(LDO5, LDO_VIN2, 0x20B, 0x40, 0x20F, 0x7f, 0x20B, 0x30, 0x20B, 0x04,
+       MT6360_REGULATOR_DESC("ldo5", LDO5, LDO_VIN2,
+                             0x20B, 0x40, 0x20F, 0x7f, 0x20B, 0x30, 0x20B, 0x04,
                              ldo_vout_ranges3, 128, 100, ldo5_irq_tbls),
 };
 
index 656fe330d38f0adbc953b8d42861088a6eaa757b..063e12c08e75f70c002e6f3e859a8bba5e8ef344 100644 (file)
@@ -140,6 +140,7 @@ static const struct of_device_id qcom_refgen_match_table[] = {
        { .compatible = "qcom,sm8250-refgen-regulator", .data = &sm8250_refgen_desc },
        { }
 };
+MODULE_DEVICE_TABLE(of, qcom_refgen_match_table);
 
 static struct platform_driver qcom_refgen_driver = {
        .probe = qcom_refgen_probe,
index 086da36abc0b4917a26fc78745dfdb8a48b5cfd5..4955616517ce9caa22f652e9370e7d517098b378 100644 (file)
@@ -84,6 +84,7 @@ static const struct of_device_id regulator_ipq4019_of_match[] = {
        { .compatible = "qcom,vqmmc-ipq4019-regulator", },
        {},
 };
+MODULE_DEVICE_TABLE(of, regulator_ipq4019_of_match);
 
 static struct platform_driver ipq4019_regulator_driver = {
        .probe = ipq4019_regulator_probe,
index 37173cb0f5f5a222b936029b8ff8e7997c401d4d..c57694be9bd32ef8cb9dc8ad794379ef2da44640 100644 (file)
@@ -162,7 +162,8 @@ struct raw3270_request *raw3270_request_alloc(size_t size)
        /*
         * Setup ccw.
         */
-       rq->ccw.cda = virt_to_dma32(rq->buffer);
+       if (rq->buffer)
+               rq->ccw.cda = virt_to_dma32(rq->buffer);
        rq->ccw.flags = CCW_FLAG_SLI;
 
        return rq;
@@ -188,7 +189,8 @@ int raw3270_request_reset(struct raw3270_request *rq)
                return -EBUSY;
        rq->ccw.cmd_code = 0;
        rq->ccw.count = 0;
-       rq->ccw.cda = virt_to_dma32(rq->buffer);
+       if (rq->buffer)
+               rq->ccw.cda = virt_to_dma32(rq->buffer);
        rq->ccw.flags = CCW_FLAG_SLI;
        rq->rescnt = 0;
        rq->rc = 0;
index 8613fa937237bde02368523577a485b62b07c5dc..a2e771ebae8ebd55e1cb841f76b44a69ebb2bea7 100644 (file)
@@ -95,7 +95,7 @@ static ssize_t crw_inject_write(struct file *file, const char __user *buf,
                return -EINVAL;
        }
 
-       buffer = vmemdup_user(buf, lbuf);
+       buffer = memdup_user_nul(buf, lbuf);
        if (IS_ERR(buffer))
                return -ENOMEM;
 
index f95d12345d98a6dbfd1efa850829586852d409ab..920f550bc313bf6c036ed11c539d4319852cb2dd 100644 (file)
@@ -363,10 +363,8 @@ int ccw_device_set_online(struct ccw_device *cdev)
 
        spin_lock_irq(cdev->ccwlock);
        ret = ccw_device_online(cdev);
-       spin_unlock_irq(cdev->ccwlock);
-       if (ret == 0)
-               wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
-       else {
+       if (ret) {
+               spin_unlock_irq(cdev->ccwlock);
                CIO_MSG_EVENT(0, "ccw_device_online returned %d, "
                              "device 0.%x.%04x\n",
                              ret, cdev->private->dev_id.ssid,
@@ -375,7 +373,12 @@ int ccw_device_set_online(struct ccw_device *cdev)
                put_device(&cdev->dev);
                return ret;
        }
-       spin_lock_irq(cdev->ccwlock);
+       /* Wait until a final state is reached */
+       while (!dev_fsm_final_state(cdev)) {
+               spin_unlock_irq(cdev->ccwlock);
+               wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
+               spin_lock_irq(cdev->ccwlock);
+       }
        /* Check if online processing was successful */
        if ((cdev->private->state != DEV_STATE_ONLINE) &&
            (cdev->private->state != DEV_STATE_W4SENSE)) {
index 65d8b2cfd6262d53a03bf10295d5d6c59f518c5d..42791fa0b80e26d4246dabc18e82f2130edb9bb9 100644 (file)
@@ -504,6 +504,11 @@ callback:
                ccw_device_done(cdev, DEV_STATE_ONLINE);
                /* Deliver fake irb to device driver, if needed. */
                if (cdev->private->flags.fake_irb) {
+                       CIO_MSG_EVENT(2, "fakeirb: deliver device 0.%x.%04x intparm %lx type=%d\n",
+                                     cdev->private->dev_id.ssid,
+                                     cdev->private->dev_id.devno,
+                                     cdev->private->intparm,
+                                     cdev->private->flags.fake_irb);
                        create_fake_irb(&cdev->private->dma_area->irb,
                                        cdev->private->flags.fake_irb);
                        cdev->private->flags.fake_irb = 0;
index 40c97f8730751f2afa862ace30b16f1ade38ea80..acd6790dba4dd1311d78e05afa0f41ad5b38aa3a 100644 (file)
@@ -208,6 +208,10 @@ int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
                if (!cdev->private->flags.fake_irb) {
                        cdev->private->flags.fake_irb = FAKE_CMD_IRB;
                        cdev->private->intparm = intparm;
+                       CIO_MSG_EVENT(2, "fakeirb: queue device 0.%x.%04x intparm %lx type=%d\n",
+                                     cdev->private->dev_id.ssid,
+                                     cdev->private->dev_id.devno, intparm,
+                                     cdev->private->flags.fake_irb);
                        return 0;
                } else
                        /* There's already a fake I/O around. */
@@ -551,6 +555,10 @@ int ccw_device_tm_start_timeout_key(struct ccw_device *cdev, struct tcw *tcw,
                if (!cdev->private->flags.fake_irb) {
                        cdev->private->flags.fake_irb = FAKE_TM_IRB;
                        cdev->private->intparm = intparm;
+                       CIO_MSG_EVENT(2, "fakeirb: queue device 0.%x.%04x intparm %lx type=%d\n",
+                                     cdev->private->dev_id.ssid,
+                                     cdev->private->dev_id.devno, intparm,
+                                     cdev->private->flags.fake_irb);
                        return 0;
                } else
                        /* There's already a fake I/O around. */
index 3d9f0834c78bf1e6a55c17a21218b29bacbd1dce..a1cb39f4b7a27939dcf8ac247a30ed965957bd5e 100644 (file)
@@ -722,8 +722,8 @@ static void qdio_handle_activate_check(struct qdio_irq *irq_ptr,
        lgr_info_log();
 }
 
-static void qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat,
-                                     int dstat)
+static int qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat,
+                                    int dstat, int dcc)
 {
        DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qest irq");
 
@@ -731,15 +731,18 @@ static void qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat,
                goto error;
        if (dstat & ~(DEV_STAT_DEV_END | DEV_STAT_CHN_END))
                goto error;
+       if (dcc == 1)
+               return -EAGAIN;
        if (!(dstat & DEV_STAT_DEV_END))
                goto error;
        qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ESTABLISHED);
-       return;
+       return 0;
 
 error:
        DBF_ERROR("%4x EQ:error", irq_ptr->schid.sch_no);
        DBF_ERROR("ds: %2x cs:%2x", dstat, cstat);
        qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
+       return -EIO;
 }
 
 /* qdio interrupt handler */
@@ -748,7 +751,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
 {
        struct qdio_irq *irq_ptr = cdev->private->qdio_data;
        struct subchannel_id schid;
-       int cstat, dstat;
+       int cstat, dstat, rc, dcc;
 
        if (!intparm || !irq_ptr) {
                ccw_device_get_schid(cdev, &schid);
@@ -768,10 +771,12 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
        qdio_irq_check_sense(irq_ptr, irb);
        cstat = irb->scsw.cmd.cstat;
        dstat = irb->scsw.cmd.dstat;
+       dcc   = scsw_cmd_is_valid_cc(&irb->scsw) ? irb->scsw.cmd.cc : 0;
+       rc    = 0;
 
        switch (irq_ptr->state) {
        case QDIO_IRQ_STATE_INACTIVE:
-               qdio_establish_handle_irq(irq_ptr, cstat, dstat);
+               rc = qdio_establish_handle_irq(irq_ptr, cstat, dstat, dcc);
                break;
        case QDIO_IRQ_STATE_CLEANUP:
                qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
@@ -785,12 +790,25 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
                if (cstat || dstat)
                        qdio_handle_activate_check(irq_ptr, intparm, cstat,
                                                   dstat);
+               else if (dcc == 1)
+                       rc = -EAGAIN;
                break;
        case QDIO_IRQ_STATE_STOPPED:
                break;
        default:
                WARN_ON_ONCE(1);
        }
+
+       if (rc == -EAGAIN) {
+               DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qint retry");
+               rc = ccw_device_start(cdev, irq_ptr->ccw, intparm, 0, 0);
+               if (!rc)
+                       return;
+               DBF_ERROR("%4x RETRY ERR", irq_ptr->schid.sch_no);
+               DBF_ERROR("rc:%4x", rc);
+               qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
+       }
+
        wake_up(&cdev->private->wait_q);
 }
 
index 0a3a678ffc7eedb237f3bc72e21ffe4c076c1444..6087547328ce91271eeab7a13c02059299c0c39a 100644 (file)
@@ -658,7 +658,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain,
                               (int)prepcblk->ccp_rtcode,
                               (int)prepcblk->ccp_rscode);
                if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
-                       rc = -EAGAIN;
+                       rc = -EBUSY;
                else
                        rc = -EIO;
                goto out;
@@ -1263,7 +1263,7 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
                               (int)prepcblk->ccp_rtcode,
                               (int)prepcblk->ccp_rscode);
                if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
-                       rc = -EAGAIN;
+                       rc = -EBUSY;
                else
                        rc = -EIO;
                goto out;
@@ -1426,7 +1426,7 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
                               (int)prepcblk->ccp_rtcode,
                               (int)prepcblk->ccp_rscode);
                if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
-                       rc = -EAGAIN;
+                       rc = -EBUSY;
                else
                        rc = -EIO;
                goto out;
index eb7f5489ccf95962034a2a135dbc30fa83599973..9bcf8fc69ebe428bff07458406f70be0407d0b39 100644 (file)
@@ -556,13 +556,29 @@ static int check_reply_pl(const u8 *pl, const char *func)
        pl += 2;
        ret = *((u32 *)pl);
        if (ret != 0) {
-               ZCRYPT_DBF_ERR("%s return value 0x%04x != 0\n", func, ret);
+               ZCRYPT_DBF_ERR("%s return value 0x%08x != 0\n", func, ret);
                return -EIO;
        }
 
        return 0;
 }
 
+/* Check ep11 reply cprb, return 0 or suggested errno value. */
+static int check_reply_cprb(const struct ep11_cprb *rep, const char *func)
+{
+       /* check ep11 reply return code field */
+       if (rep->ret_code) {
+               ZCRYPT_DBF_ERR("%s ep11 reply ret_code=0x%08x\n", __func__,
+                              rep->ret_code);
+               if (rep->ret_code == 0x000c0003)
+                       return -EBUSY;
+               else
+                       return -EIO;
+       }
+
+       return 0;
+}
+
 /*
  * Helper function which does an ep11 query with given query type.
  */
@@ -627,6 +643,12 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
                goto out;
        }
 
+       /* check ep11 reply cprb */
+       rc = check_reply_cprb(rep, __func__);
+       if (rc)
+               goto out;
+
+       /* check payload */
        rc = check_reply_pl((u8 *)rep_pl, __func__);
        if (rc)
                goto out;
@@ -877,6 +899,12 @@ static int _ep11_genaeskey(u16 card, u16 domain,
                goto out;
        }
 
+       /* check ep11 reply cprb */
+       rc = check_reply_cprb(rep, __func__);
+       if (rc)
+               goto out;
+
+       /* check payload */
        rc = check_reply_pl((u8 *)rep_pl, __func__);
        if (rc)
                goto out;
@@ -1028,6 +1056,12 @@ static int ep11_cryptsingle(u16 card, u16 domain,
                goto out;
        }
 
+       /* check ep11 reply cprb */
+       rc = check_reply_cprb(rep, __func__);
+       if (rc)
+               goto out;
+
+       /* check payload */
        rc = check_reply_pl((u8 *)rep_pl, __func__);
        if (rc)
                goto out;
@@ -1185,6 +1219,12 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
                goto out;
        }
 
+       /* check ep11 reply cprb */
+       rc = check_reply_cprb(rep, __func__);
+       if (rc)
+               goto out;
+
+       /* check payload */
        rc = check_reply_pl((u8 *)rep_pl, __func__);
        if (rc)
                goto out;
@@ -1339,6 +1379,12 @@ static int _ep11_wrapkey(u16 card, u16 domain,
                goto out;
        }
 
+       /* check ep11 reply cprb */
+       rc = check_reply_cprb(rep, __func__);
+       if (rc)
+               goto out;
+
+       /* check payload */
        rc = check_reply_pl((u8 *)rep_pl, __func__);
        if (rc)
                goto out;
index 2c8e964425dc38ca80fa5009b17b4e9dc29bbf10..43778b088ffac54c4a8911f3e41e187f0ae3f364 100644 (file)
@@ -292,13 +292,16 @@ out:
 static void ism_free_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
 {
        clear_bit(dmb->sba_idx, ism->sba_bitmap);
-       dma_free_coherent(&ism->pdev->dev, dmb->dmb_len,
-                         dmb->cpu_addr, dmb->dma_addr);
+       dma_unmap_page(&ism->pdev->dev, dmb->dma_addr, dmb->dmb_len,
+                      DMA_FROM_DEVICE);
+       folio_put(virt_to_folio(dmb->cpu_addr));
 }
 
 static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
 {
+       struct folio *folio;
        unsigned long bit;
+       int rc;
 
        if (PAGE_ALIGN(dmb->dmb_len) > dma_get_max_seg_size(&ism->pdev->dev))
                return -EINVAL;
@@ -315,14 +318,30 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
            test_and_set_bit(dmb->sba_idx, ism->sba_bitmap))
                return -EINVAL;
 
-       dmb->cpu_addr = dma_alloc_coherent(&ism->pdev->dev, dmb->dmb_len,
-                                          &dmb->dma_addr,
-                                          GFP_KERNEL | __GFP_NOWARN |
-                                          __GFP_NOMEMALLOC | __GFP_NORETRY);
-       if (!dmb->cpu_addr)
-               clear_bit(dmb->sba_idx, ism->sba_bitmap);
+       folio = folio_alloc(GFP_KERNEL | __GFP_NOWARN | __GFP_NOMEMALLOC |
+                           __GFP_NORETRY, get_order(dmb->dmb_len));
 
-       return dmb->cpu_addr ? 0 : -ENOMEM;
+       if (!folio) {
+               rc = -ENOMEM;
+               goto out_bit;
+       }
+
+       dmb->cpu_addr = folio_address(folio);
+       dmb->dma_addr = dma_map_page(&ism->pdev->dev,
+                                    virt_to_page(dmb->cpu_addr), 0,
+                                    dmb->dmb_len, DMA_FROM_DEVICE);
+       if (dma_mapping_error(&ism->pdev->dev, dmb->dma_addr)) {
+               rc = -ENOMEM;
+               goto out_free;
+       }
+
+       return 0;
+
+out_free:
+       kfree(dmb->cpu_addr);
+out_bit:
+       clear_bit(dmb->sba_idx, ism->sba_bitmap);
+       return rc;
 }
 
 int ism_register_dmb(struct ism_dev *ism, struct ism_dmb *dmb,
index f0b8b709649f29691c3d0976b8a1156da1f6bd81..a3adaec5504e45384eeedf8f82ee160317fcbbf5 100644 (file)
@@ -364,30 +364,33 @@ out:
        return rc;
 }
 
+static void qeth_free_cq(struct qeth_card *card)
+{
+       if (card->qdio.c_q) {
+               qeth_free_qdio_queue(card->qdio.c_q);
+               card->qdio.c_q = NULL;
+       }
+}
+
 static int qeth_alloc_cq(struct qeth_card *card)
 {
        if (card->options.cq == QETH_CQ_ENABLED) {
                QETH_CARD_TEXT(card, 2, "cqon");
-               card->qdio.c_q = qeth_alloc_qdio_queue();
                if (!card->qdio.c_q) {
-                       dev_err(&card->gdev->dev, "Failed to create completion queue\n");
-                       return -ENOMEM;
+                       card->qdio.c_q = qeth_alloc_qdio_queue();
+                       if (!card->qdio.c_q) {
+                               dev_err(&card->gdev->dev,
+                                       "Failed to create completion queue\n");
+                               return -ENOMEM;
+                       }
                }
        } else {
                QETH_CARD_TEXT(card, 2, "nocq");
-               card->qdio.c_q = NULL;
+               qeth_free_cq(card);
        }
        return 0;
 }
 
-static void qeth_free_cq(struct qeth_card *card)
-{
-       if (card->qdio.c_q) {
-               qeth_free_qdio_queue(card->qdio.c_q);
-               card->qdio.c_q = NULL;
-       }
-}
-
 static enum iucv_tx_notify qeth_compute_cq_notification(int sbalf15,
                                                        int delayed)
 {
@@ -2628,6 +2631,10 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card)
 
        QETH_CARD_TEXT(card, 2, "allcqdbf");
 
+       /* completion */
+       if (qeth_alloc_cq(card))
+               goto out_err;
+
        if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED,
                QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
                return 0;
@@ -2663,10 +2670,6 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card)
                queue->priority = QETH_QIB_PQUE_PRIO_DEFAULT;
        }
 
-       /* completion */
-       if (qeth_alloc_cq(card))
-               goto out_freeoutq;
-
        return 0;
 
 out_freeoutq:
@@ -2677,6 +2680,8 @@ out_freeoutq:
        qeth_free_buffer_pool(card);
 out_buffer_pool:
        atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
+       qeth_free_cq(card);
+out_err:
        return -ENOMEM;
 }
 
@@ -2684,11 +2689,12 @@ static void qeth_free_qdio_queues(struct qeth_card *card)
 {
        int i, j;
 
+       qeth_free_cq(card);
+
        if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
                QETH_QDIO_UNINITIALIZED)
                return;
 
-       qeth_free_cq(card);
        for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
                if (card->qdio.in_q->bufs[j].rx_skb) {
                        consume_skb(card->qdio.in_q->bufs[j].rx_skb);
@@ -3742,24 +3748,11 @@ static void qeth_qdio_poll(struct ccw_device *cdev, unsigned long card_ptr)
 
 int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq)
 {
-       int rc;
-
-       if (card->options.cq ==  QETH_CQ_NOTAVAILABLE) {
-               rc = -1;
-               goto out;
-       } else {
-               if (card->options.cq == cq) {
-                       rc = 0;
-                       goto out;
-               }
-
-               qeth_free_qdio_queues(card);
-               card->options.cq = cq;
-               rc = 0;
-       }
-out:
-       return rc;
+       if (card->options.cq == QETH_CQ_NOTAVAILABLE)
+               return -1;
 
+       card->options.cq = cq;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(qeth_configure_cq);
 
index 2e28e2360c85740d0b3ebb391785ee111c78d47b..5b3230ef51fe61bce58ba1cc83bff7cb0a6ddbc1 100644 (file)
@@ -635,10 +635,9 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
        if (blk_queue_add_random(q))
                add_disk_randomness(req->q->disk);
 
-       if (!blk_rq_is_passthrough(req)) {
-               WARN_ON_ONCE(!(cmd->flags & SCMD_INITIALIZED));
-               cmd->flags &= ~SCMD_INITIALIZED;
-       }
+       WARN_ON_ONCE(!blk_rq_is_passthrough(req) &&
+                    !(cmd->flags & SCMD_INITIALIZED));
+       cmd->flags = 0;
 
        /*
         * Calling rcu_barrier() is not necessary here because the
index 58fdf679341dc64ee1768f1d09dc7ce4d549b4bd..65cdc8b77e358546fd1768fe4ec1bb4588c4b692 100644 (file)
@@ -3120,6 +3120,7 @@ static void sd_read_io_hints(struct scsi_disk *sdkp, unsigned char *buffer)
 {
        struct scsi_device *sdp = sdkp->device;
        const struct scsi_io_group_descriptor *desc, *start, *end;
+       u16 permanent_stream_count_old;
        struct scsi_sense_hdr sshdr;
        struct scsi_mode_data data;
        int res;
@@ -3140,12 +3141,13 @@ static void sd_read_io_hints(struct scsi_disk *sdkp, unsigned char *buffer)
        for (desc = start; desc < end; desc++)
                if (!desc->st_enble || !sd_is_perm_stream(sdkp, desc - start))
                        break;
+       permanent_stream_count_old = sdkp->permanent_stream_count;
        sdkp->permanent_stream_count = desc - start;
        if (sdkp->rscs && sdkp->permanent_stream_count < 2)
                sd_printk(KERN_INFO, sdkp,
                          "Unexpected: RSCS has been set and the permanent stream count is %u\n",
                          sdkp->permanent_stream_count);
-       else if (sdkp->permanent_stream_count)
+       else if (sdkp->permanent_stream_count != permanent_stream_count_old)
                sd_printk(KERN_INFO, sdkp, "permanent stream count = %d\n",
                          sdkp->permanent_stream_count);
 }
index efeba8275a6691e20be511e4dcef6ce15e087b61..a09a26bf4988ff200e4f9aa177edd0eb04e9e62f 100644 (file)
@@ -1451,7 +1451,11 @@ static void qcom_slim_ngd_up_worker(struct work_struct *work)
        ctrl = container_of(work, struct qcom_slim_ngd_ctrl, ngd_up_work);
 
        /* Make sure qmi service is up before continuing */
-       wait_for_completion_interruptible(&ctrl->qmi_up);
+       if (!wait_for_completion_interruptible_timeout(&ctrl->qmi_up,
+                                                      msecs_to_jiffies(MSEC_PER_SEC))) {
+               dev_err(ctrl->dev, "QMI wait timeout\n");
+               return;
+       }
 
        mutex_lock(&ctrl->ssr_lock);
        qcom_slim_ngd_enable(ctrl, true);
index 50c664b65f4d44ada7892098029ee25b7a3af876..1b7afb19ccd637471ad82ad833f589cb0f9405b1 100644 (file)
@@ -72,6 +72,7 @@ config MTK_SOCINFO
        tristate "MediaTek SoC Information"
        default y
        depends on NVMEM_MTK_EFUSE
+       select SOC_BUS
        help
          The MediaTek SoC Information (mtk-socinfo) driver provides
          information about the SoC to the userspace including the
index c832f5c670bcf00bcc6faae0ee0b8802405a9ce0..9a91298c125397c7aa1649d008fbab5c810a4575 100644 (file)
@@ -1768,6 +1768,7 @@ static int svs_bank_resource_setup(struct svs_platform *svsp)
        const struct svs_bank_pdata *bdata;
        struct svs_bank *svsb;
        struct dev_pm_opp *opp;
+       char tz_name_buf[20];
        unsigned long freq;
        int count, ret;
        u32 idx, i;
@@ -1819,10 +1820,12 @@ static int svs_bank_resource_setup(struct svs_platform *svsp)
                }
 
                if (!IS_ERR_OR_NULL(bdata->tzone_name)) {
-                       svsb->tzd = thermal_zone_get_zone_by_name(bdata->tzone_name);
+                       snprintf(tz_name_buf, ARRAY_SIZE(tz_name_buf),
+                                "%s-thermal", bdata->tzone_name);
+                       svsb->tzd = thermal_zone_get_zone_by_name(tz_name_buf);
                        if (IS_ERR(svsb->tzd)) {
                                dev_err(svsb->dev, "cannot get \"%s\" thermal zone\n",
-                                       bdata->tzone_name);
+                                       tz_name_buf);
                                return PTR_ERR(svsb->tzd);
                        }
                }
index 7cd24bd8e2248ef9c0e5fece95b3fb58e94f4e1e..6bcf8e75273c4e03cff5823dd77bc5ac38fd2360 100644 (file)
@@ -130,6 +130,19 @@ static void amd_sdw_set_frameshape(struct amd_sdw_manager *amd_manager)
        writel(frame_size, amd_manager->mmio + ACP_SW_FRAMESIZE);
 }
 
+static void amd_sdw_wake_enable(struct amd_sdw_manager *amd_manager, bool enable)
+{
+       u32 wake_ctrl;
+
+       wake_ctrl = readl(amd_manager->mmio + ACP_SW_STATE_CHANGE_STATUS_MASK_8TO11);
+       if (enable)
+               wake_ctrl |= AMD_SDW_WAKE_INTR_MASK;
+       else
+               wake_ctrl &= ~AMD_SDW_WAKE_INTR_MASK;
+
+       writel(wake_ctrl, amd_manager->mmio + ACP_SW_STATE_CHANGE_STATUS_MASK_8TO11);
+}
+
 static void amd_sdw_ctl_word_prep(u32 *lower_word, u32 *upper_word, struct sdw_msg *msg,
                                  int cmd_offset)
 {
@@ -1095,6 +1108,7 @@ static int __maybe_unused amd_suspend(struct device *dev)
        }
 
        if (amd_manager->power_mode_mask & AMD_SDW_CLK_STOP_MODE) {
+               amd_sdw_wake_enable(amd_manager, false);
                return amd_sdw_clock_stop(amd_manager);
        } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) {
                /*
@@ -1121,6 +1135,7 @@ static int __maybe_unused amd_suspend_runtime(struct device *dev)
                return 0;
        }
        if (amd_manager->power_mode_mask & AMD_SDW_CLK_STOP_MODE) {
+               amd_sdw_wake_enable(amd_manager, true);
                return amd_sdw_clock_stop(amd_manager);
        } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) {
                ret = amd_sdw_clock_stop(amd_manager);
index 418b679e0b1a684e0a3ac502d94f74d24d24c00d..707065468e05a038acb1a1c893133b5d757a4de8 100644 (file)
 #define AMD_SDW0_EXT_INTR_MASK         0x200000
 #define AMD_SDW1_EXT_INTR_MASK         4
 #define AMD_SDW_IRQ_MASK_0TO7          0x77777777
-#define AMD_SDW_IRQ_MASK_8TO11         0x000d7777
+#define AMD_SDW_IRQ_MASK_8TO11         0x000c7777
 #define AMD_SDW_IRQ_ERROR_MASK         0xff
 #define AMD_SDW_MAX_FREQ_NUM           1
 #define AMD_SDW0_MAX_TX_PORTS          3
 #define AMD_SDW_CLK_RESUME_REQ                         2
 #define AMD_SDW_CLK_RESUME_DONE                                3
 #define AMD_SDW_WAKE_STAT_MASK                         BIT(16)
+#define AMD_SDW_WAKE_INTR_MASK                         BIT(16)
 
 static u32 amd_sdw_freq_tbl[AMD_SDW_MAX_FREQ_NUM] = {
        AMD_SDW_DEFAULT_CLK_FREQ,
index 7cc219d78551adbcd99e10e4d59f50653276cac1..e358ac5b4509777e0827630e2f6e58c385f9a54c 100644 (file)
@@ -623,7 +623,7 @@ static int spi_engine_probe(struct platform_device *pdev)
 
        version = readl(spi_engine->base + ADI_AXI_REG_VERSION);
        if (ADI_AXI_PCORE_VER_MAJOR(version) != 1) {
-               dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%c\n",
+               dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%u\n",
                        ADI_AXI_PCORE_VER_MAJOR(version),
                        ADI_AXI_PCORE_VER_MINOR(version),
                        ADI_AXI_PCORE_VER_PATCH(version));
index 35ef5e8e2ffd253ce16ea0594b2cabcf579cff77..77e9738e42f60ec844c74f09dddf5d90e898d87d 100644 (file)
@@ -151,8 +151,6 @@ static const struct debugfs_reg32 hisi_spi_regs[] = {
        HISI_SPI_DBGFS_REG("ENR", HISI_SPI_ENR),
        HISI_SPI_DBGFS_REG("FIFOC", HISI_SPI_FIFOC),
        HISI_SPI_DBGFS_REG("IMR", HISI_SPI_IMR),
-       HISI_SPI_DBGFS_REG("DIN", HISI_SPI_DIN),
-       HISI_SPI_DBGFS_REG("DOUT", HISI_SPI_DOUT),
        HISI_SPI_DBGFS_REG("SR", HISI_SPI_SR),
        HISI_SPI_DBGFS_REG("RISR", HISI_SPI_RISR),
        HISI_SPI_DBGFS_REG("ISR", HISI_SPI_ISR),
index ff75838c1b5dfa44fccca525c3a8a334051167fb..a2c467d9e92f59c46eea6ec78b3b12a9ae5a6caf 100644 (file)
@@ -4523,6 +4523,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message)
                wait_for_completion(&done);
                status = message->status;
        }
+       message->complete = NULL;
        message->context = NULL;
 
        return status;
index c617e8b9f0ddfe18bcb34155e156af47e4006837..5693cc8b231aacdcf0a90f363a89e15f7bcd93f8 100644 (file)
@@ -139,11 +139,13 @@ struct tz_episode {
  * we keep track of the current position in the history array.
  *
  * @tz_episodes: a list of thermal mitigation episodes
+ * @tz: thermal zone this object belongs to
  * @trips_crossed: an array of trip points crossed by id
  * @nr_trips: the number of trip points currently being crossed
  */
 struct tz_debugfs {
        struct list_head tz_episodes;
+       struct thermal_zone_device *tz;
        int *trips_crossed;
        int nr_trips;
 };
@@ -503,15 +505,23 @@ void thermal_debug_cdev_add(struct thermal_cooling_device *cdev)
  */
 void thermal_debug_cdev_remove(struct thermal_cooling_device *cdev)
 {
-       struct thermal_debugfs *thermal_dbg = cdev->debugfs;
+       struct thermal_debugfs *thermal_dbg;
 
-       if (!thermal_dbg)
+       mutex_lock(&cdev->lock);
+
+       thermal_dbg = cdev->debugfs;
+       if (!thermal_dbg) {
+               mutex_unlock(&cdev->lock);
                return;
+       }
+
+       cdev->debugfs = NULL;
+
+       mutex_unlock(&cdev->lock);
 
        mutex_lock(&thermal_dbg->lock);
 
        thermal_debugfs_cdev_clear(&thermal_dbg->cdev_dbg);
-       cdev->debugfs = NULL;
 
        mutex_unlock(&thermal_dbg->lock);
 
@@ -616,6 +626,7 @@ void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
        tze->trip_stats[trip_id].timestamp = now;
        tze->trip_stats[trip_id].max = max(tze->trip_stats[trip_id].max, temperature);
        tze->trip_stats[trip_id].min = min(tze->trip_stats[trip_id].min, temperature);
+       tze->trip_stats[trip_id].count++;
        tze->trip_stats[trip_id].avg = tze->trip_stats[trip_id].avg +
                (temperature - tze->trip_stats[trip_id].avg) /
                tze->trip_stats[trip_id].count;
@@ -715,8 +726,7 @@ out:
 
 static void *tze_seq_start(struct seq_file *s, loff_t *pos)
 {
-       struct thermal_zone_device *tz = s->private;
-       struct thermal_debugfs *thermal_dbg = tz->debugfs;
+       struct thermal_debugfs *thermal_dbg = s->private;
        struct tz_debugfs *tz_dbg = &thermal_dbg->tz_dbg;
 
        mutex_lock(&thermal_dbg->lock);
@@ -726,8 +736,7 @@ static void *tze_seq_start(struct seq_file *s, loff_t *pos)
 
 static void *tze_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-       struct thermal_zone_device *tz = s->private;
-       struct thermal_debugfs *thermal_dbg = tz->debugfs;
+       struct thermal_debugfs *thermal_dbg = s->private;
        struct tz_debugfs *tz_dbg = &thermal_dbg->tz_dbg;
 
        return seq_list_next(v, &tz_dbg->tz_episodes, pos);
@@ -735,15 +744,15 @@ static void *tze_seq_next(struct seq_file *s, void *v, loff_t *pos)
 
 static void tze_seq_stop(struct seq_file *s, void *v)
 {
-       struct thermal_zone_device *tz = s->private;
-       struct thermal_debugfs *thermal_dbg = tz->debugfs;
+       struct thermal_debugfs *thermal_dbg = s->private;
 
        mutex_unlock(&thermal_dbg->lock);
 }
 
 static int tze_seq_show(struct seq_file *s, void *v)
 {
-       struct thermal_zone_device *tz = s->private;
+       struct thermal_debugfs *thermal_dbg = s->private;
+       struct thermal_zone_device *tz = thermal_dbg->tz_dbg.tz;
        struct thermal_trip *trip;
        struct tz_episode *tze;
        const char *type;
@@ -809,6 +818,8 @@ void thermal_debug_tz_add(struct thermal_zone_device *tz)
 
        tz_dbg = &thermal_dbg->tz_dbg;
 
+       tz_dbg->tz = tz;
+
        tz_dbg->trips_crossed = kzalloc(sizeof(int) * tz->num_trips, GFP_KERNEL);
        if (!tz_dbg->trips_crossed) {
                thermal_debugfs_remove_id(thermal_dbg);
@@ -817,23 +828,44 @@ void thermal_debug_tz_add(struct thermal_zone_device *tz)
 
        INIT_LIST_HEAD(&tz_dbg->tz_episodes);
 
-       debugfs_create_file("mitigations", 0400, thermal_dbg->d_top, tz, &tze_fops);
+       debugfs_create_file("mitigations", 0400, thermal_dbg->d_top,
+                           thermal_dbg, &tze_fops);
 
        tz->debugfs = thermal_dbg;
 }
 
 void thermal_debug_tz_remove(struct thermal_zone_device *tz)
 {
-       struct thermal_debugfs *thermal_dbg = tz->debugfs;
+       struct thermal_debugfs *thermal_dbg;
+       struct tz_episode *tze, *tmp;
+       struct tz_debugfs *tz_dbg;
+       int *trips_crossed;
 
-       if (!thermal_dbg)
+       mutex_lock(&tz->lock);
+
+       thermal_dbg = tz->debugfs;
+       if (!thermal_dbg) {
+               mutex_unlock(&tz->lock);
                return;
+       }
+
+       tz->debugfs = NULL;
+
+       mutex_unlock(&tz->lock);
+
+       tz_dbg = &thermal_dbg->tz_dbg;
 
        mutex_lock(&thermal_dbg->lock);
 
-       tz->debugfs = NULL;
+       trips_crossed = tz_dbg->trips_crossed;
+
+       list_for_each_entry_safe(tze, tmp, &tz_dbg->tz_episodes, node) {
+               list_del(&tze->node);
+               kfree(tze);
+       }
 
        mutex_unlock(&thermal_dbg->lock);
 
        thermal_debugfs_remove_id(thermal_dbg);
+       kfree(trips_crossed);
 }
index 6ffc4e81ffed78bedaac182b5a77742390c6cd74..326433df5880e26cfef2bc4ce13fdbf37e6b79be 100644 (file)
@@ -3180,22 +3180,29 @@ void tb_switch_unconfigure_link(struct tb_switch *sw)
 {
        struct tb_port *up, *down;
 
-       if (sw->is_unplugged)
-               return;
        if (!tb_route(sw) || tb_switch_is_icm(sw))
                return;
 
+       /*
+        * Unconfigure downstream port so that wake-on-connect can be
+        * configured after router unplug. No need to unconfigure upstream port
+        * since its router is unplugged.
+        */
        up = tb_upstream_port(sw);
-       if (tb_switch_is_usb4(up->sw))
-               usb4_port_unconfigure(up);
-       else
-               tb_lc_unconfigure_port(up);
-
        down = up->remote;
        if (tb_switch_is_usb4(down->sw))
                usb4_port_unconfigure(down);
        else
                tb_lc_unconfigure_port(down);
+
+       if (sw->is_unplugged)
+               return;
+
+       up = tb_upstream_port(sw);
+       if (tb_switch_is_usb4(up->sw))
+               usb4_port_unconfigure(up);
+       else
+               tb_lc_unconfigure_port(up);
 }
 
 static void tb_switch_credits_init(struct tb_switch *sw)
@@ -3441,7 +3448,26 @@ static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags)
        return tb_lc_set_wake(sw, flags);
 }
 
-int tb_switch_resume(struct tb_switch *sw)
+static void tb_switch_check_wakes(struct tb_switch *sw)
+{
+       if (device_may_wakeup(&sw->dev)) {
+               if (tb_switch_is_usb4(sw))
+                       usb4_switch_check_wakes(sw);
+       }
+}
+
+/**
+ * tb_switch_resume() - Resume a switch after sleep
+ * @sw: Switch to resume
+ * @runtime: Is this resume from runtime suspend or system sleep
+ *
+ * Resumes and re-enumerates router (and all its children), if still plugged
+ * after suspend. Don't enumerate device router whose UID was changed during
+ * suspend. If this is resume from system sleep, notifies PM core about the
+ * wakes occurred during suspend. Disables all wakes, except USB4 wake of
+ * upstream port for USB4 routers that shall be always enabled.
+ */
+int tb_switch_resume(struct tb_switch *sw, bool runtime)
 {
        struct tb_port *port;
        int err;
@@ -3490,6 +3516,9 @@ int tb_switch_resume(struct tb_switch *sw)
        if (err)
                return err;
 
+       if (!runtime)
+               tb_switch_check_wakes(sw);
+
        /* Disable wakes */
        tb_switch_set_wake(sw, 0);
 
@@ -3519,7 +3548,8 @@ int tb_switch_resume(struct tb_switch *sw)
                         */
                        if (tb_port_unlock(port))
                                tb_port_warn(port, "failed to unlock port\n");
-                       if (port->remote && tb_switch_resume(port->remote->sw)) {
+                       if (port->remote &&
+                           tb_switch_resume(port->remote->sw, runtime)) {
                                tb_port_warn(port,
                                             "lost during suspend, disconnecting\n");
                                tb_sw_set_unplugged(port->remote->sw);
index c5ce7a694b27df774aeb0e9d6bf8fd7c1cd6a82e..3e44c78ac40929289bb745584a232ca1913ad3ab 100644 (file)
@@ -1801,6 +1801,12 @@ static struct tb_port *tb_find_dp_out(struct tb *tb, struct tb_port *in)
                        continue;
                }
 
+               /* Needs to be on different routers */
+               if (in->sw == port->sw) {
+                       tb_port_dbg(port, "skipping DP OUT on same router\n");
+                       continue;
+               }
+
                tb_port_dbg(port, "DP OUT available\n");
 
                /*
@@ -2936,7 +2942,7 @@ static int tb_resume_noirq(struct tb *tb)
        if (!tb_switch_is_usb4(tb->root_switch))
                tb_switch_reset(tb->root_switch);
 
-       tb_switch_resume(tb->root_switch);
+       tb_switch_resume(tb->root_switch, false);
        tb_free_invalid_tunnels(tb);
        tb_free_unplugged_children(tb->root_switch);
        tb_restore_children(tb->root_switch);
@@ -3062,7 +3068,7 @@ static int tb_runtime_resume(struct tb *tb)
        struct tb_tunnel *tunnel, *n;
 
        mutex_lock(&tb->lock);
-       tb_switch_resume(tb->root_switch);
+       tb_switch_resume(tb->root_switch, true);
        tb_free_invalid_tunnels(tb);
        tb_restore_children(tb->root_switch);
        list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list)
index feed8ecaf712e84409daacb6a55b3ef121cb05f0..18aae4ccaed596571de43c4c65ceafff93c267bd 100644 (file)
@@ -827,7 +827,7 @@ int tb_switch_configuration_valid(struct tb_switch *sw);
 int tb_switch_add(struct tb_switch *sw);
 void tb_switch_remove(struct tb_switch *sw);
 void tb_switch_suspend(struct tb_switch *sw, bool runtime);
-int tb_switch_resume(struct tb_switch *sw);
+int tb_switch_resume(struct tb_switch *sw, bool runtime);
 int tb_switch_reset(struct tb_switch *sw);
 int tb_switch_wait_for_bit(struct tb_switch *sw, u32 offset, u32 bit,
                           u32 value, int timeout_msec);
@@ -1288,6 +1288,7 @@ static inline bool tb_switch_is_usb4(const struct tb_switch *sw)
        return usb4_switch_version(sw) > 0;
 }
 
+void usb4_switch_check_wakes(struct tb_switch *sw);
 int usb4_switch_setup(struct tb_switch *sw);
 int usb4_switch_configuration_valid(struct tb_switch *sw);
 int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid);
index 9860b49d7a2b201c9db051c06243fbf4d7b59fb8..78b06e922fdace678239dae417183219b0ae2007 100644 (file)
@@ -155,7 +155,13 @@ static inline int usb4_switch_op_data(struct tb_switch *sw, u16 opcode,
                                tx_dwords, rx_data, rx_dwords);
 }
 
-static void usb4_switch_check_wakes(struct tb_switch *sw)
+/**
+ * usb4_switch_check_wakes() - Check for wakes and notify PM core about them
+ * @sw: Router whose wakes to check
+ *
+ * Checks wakes occurred during suspend and notify the PM core about them.
+ */
+void usb4_switch_check_wakes(struct tb_switch *sw)
 {
        bool wakeup_usb4 = false;
        struct usb4_port *usb4;
@@ -163,9 +169,6 @@ static void usb4_switch_check_wakes(struct tb_switch *sw)
        bool wakeup = false;
        u32 val;
 
-       if (!device_may_wakeup(&sw->dev))
-               return;
-
        if (tb_route(sw)) {
                if (tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_6, 1))
                        return;
@@ -244,8 +247,6 @@ int usb4_switch_setup(struct tb_switch *sw)
        u32 val = 0;
        int ret;
 
-       usb4_switch_check_wakes(sw);
-
        if (!tb_route(sw))
                return 0;
 
index a3acbf0f5da1beff6724e839fa14a0a990a15576..1300c92b8702a3237459190d9027f12319581b25 100644 (file)
@@ -356,9 +356,9 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
        long rate;
        int ret;
 
+       clk_disable_unprepare(d->clk);
        rate = clk_round_rate(d->clk, newrate);
-       if (rate > 0 && p->uartclk != rate) {
-               clk_disable_unprepare(d->clk);
+       if (rate > 0) {
                /*
                 * Note that any clock-notifer worker will block in
                 * serial8250_update_uartclk() until we are done.
@@ -366,8 +366,8 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
                ret = clk_set_rate(d->clk, newrate);
                if (!ret)
                        p->uartclk = rate;
-               clk_prepare_enable(d->clk);
        }
+       clk_prepare_enable(d->clk);
 
        dw8250_do_set_termios(p, termios, old);
 }
index 7984ee05af1dada214e275062a5c831d9a66144c..47e1a056a60c34b49f37dc4aa0f0c3963bf78bef 100644 (file)
@@ -151,7 +151,7 @@ static int lpc18xx_serial_probe(struct platform_device *pdev)
 
        ret = uart_read_port_properties(&uart.port);
        if (ret)
-               return ret;
+               goto dis_uart_clk;
 
        uart.port.iotype = UPIO_MEM32;
        uart.port.regshift = 2;
index 0d35c77fad9eb1a700baeff700d4c83d38b8a2fd..e2e4f99f9d3471ed414e24aac88cfaab029b6ae9 100644 (file)
@@ -5010,12 +5010,6 @@ static const struct pci_device_id serial_pci_tbl[] = {
        {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0,
                pbn_b0_bt_2_115200 },
-       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_A,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_115200 },
-       {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_B,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               pbn_b0_bt_2_115200 },
        {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_A,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0,
                pbn_b0_bt_4_460800 },
index 4749331fe618cad7c0af98630f90021b8244bd07..1e8853eae5042b3eb16a1ec191d6ae2970ae30dd 100644 (file)
@@ -1086,11 +1086,13 @@ static void mxs_auart_set_ldisc(struct uart_port *port,
 
 static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
 {
-       u32 istat;
+       u32 istat, stat;
        struct mxs_auart_port *s = context;
        u32 mctrl_temp = s->mctrl_prev;
-       u32 stat = mxs_read(s, REG_STAT);
 
+       uart_port_lock(&s->port);
+
+       stat = mxs_read(s, REG_STAT);
        istat = mxs_read(s, REG_INTR);
 
        /* ack irq */
@@ -1126,6 +1128,8 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
                istat &= ~AUART_INTR_TXIS;
        }
 
+       uart_port_unlock(&s->port);
+
        return IRQ_HANDLED;
 }
 
index 05d97e89511e698bee73698edd0a98a58893bb7b..92195f984de1b556767a171990a2b07f5ed33e99 100644 (file)
@@ -210,7 +210,6 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap)
 {
        struct tty_port *port;
        unsigned char ch, r1, drop, flag;
-       int loops = 0;
 
        /* Sanity check, make sure the old bug is no longer happening */
        if (uap->port.state == NULL) {
@@ -291,24 +290,11 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap)
                if (r1 & Rx_OVR)
                        tty_insert_flip_char(port, 0, TTY_OVERRUN);
        next_char:
-               /* We can get stuck in an infinite loop getting char 0 when the
-                * line is in a wrong HW state, we break that here.
-                * When that happens, I disable the receive side of the driver.
-                * Note that what I've been experiencing is a real irq loop where
-                * I'm getting flooded regardless of the actual port speed.
-                * Something strange is going on with the HW
-                */
-               if ((++loops) > 1000)
-                       goto flood;
                ch = read_zsreg(uap, R0);
                if (!(ch & Rx_CH_AV))
                        break;
        }
 
-       return true;
- flood:
-       pmz_interrupt_control(uap, 0);
-       pmz_error("pmz: rx irq flood !\n");
        return true;
 }
 
index c74c548f0db62ae97ffdfbe33390bac50c412862..b6c38d2edfd401a79a937c0d149cbbb77ee3b342 100644 (file)
@@ -22,6 +22,7 @@ struct serial_ctrl_device {
 struct serial_port_device {
        struct device dev;
        struct uart_port *port;
+       unsigned int tx_enabled:1;
 };
 
 int serial_base_ctrl_init(void);
@@ -30,6 +31,9 @@ void serial_base_ctrl_exit(void);
 int serial_base_port_init(void);
 void serial_base_port_exit(void);
 
+void serial_base_port_startup(struct uart_port *port);
+void serial_base_port_shutdown(struct uart_port *port);
+
 int serial_base_driver_register(struct device_driver *driver);
 void serial_base_driver_unregister(struct device_driver *driver);
 
index ff85ebd3a007dba0105e38d732efc0f6a6f8ab5b..c476d884356dbda13ad2183a2d7218aa88ae3325 100644 (file)
@@ -156,7 +156,7 @@ static void __uart_start(struct uart_state *state)
         * enabled, serial_port_runtime_resume() calls start_tx() again
         * after enabling the device.
         */
-       if (pm_runtime_active(&port_dev->dev))
+       if (!pm_runtime_enabled(port->dev) || pm_runtime_active(&port_dev->dev))
                port->ops->start_tx(port);
        pm_runtime_mark_last_busy(&port_dev->dev);
        pm_runtime_put_autosuspend(&port_dev->dev);
@@ -323,16 +323,26 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state,
                        bool init_hw)
 {
        struct tty_port *port = &state->port;
+       struct uart_port *uport;
        int retval;
 
        if (tty_port_initialized(port))
-               return 0;
+               goto out_base_port_startup;
 
        retval = uart_port_startup(tty, state, init_hw);
-       if (retval)
+       if (retval) {
                set_bit(TTY_IO_ERROR, &tty->flags);
+               return retval;
+       }
 
-       return retval;
+out_base_port_startup:
+       uport = uart_port_check(state);
+       if (!uport)
+               return -EIO;
+
+       serial_base_port_startup(uport);
+
+       return 0;
 }
 
 /*
@@ -355,6 +365,9 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
        if (tty)
                set_bit(TTY_IO_ERROR, &tty->flags);
 
+       if (uport)
+               serial_base_port_shutdown(uport);
+
        if (tty_port_initialized(port)) {
                tty_port_set_initialized(port, false);
 
@@ -1775,6 +1788,7 @@ static void uart_tty_port_shutdown(struct tty_port *port)
        uport->ops->stop_rx(uport);
        uart_port_unlock_irq(uport);
 
+       serial_base_port_shutdown(uport);
        uart_port_shutdown(port);
 
        /*
@@ -1788,6 +1802,7 @@ static void uart_tty_port_shutdown(struct tty_port *port)
         * Free the transmit buffer.
         */
        uart_port_lock_irq(uport);
+       uart_circ_clear(&state->xmit);
        buf = state->xmit.buf;
        state->xmit.buf = NULL;
        uart_port_unlock_irq(uport);
index 22b9eeb23e68adb2cfd949ff20c18816bb78b1cb..7e3a1c7b097c3cce20c7fe9f801c1f3dfa76f304 100644 (file)
@@ -39,8 +39,12 @@ static int serial_port_runtime_resume(struct device *dev)
 
        /* Flush any pending TX for the port */
        uart_port_lock_irqsave(port, &flags);
+       if (!port_dev->tx_enabled)
+               goto unlock;
        if (__serial_port_busy(port))
                port->ops->start_tx(port);
+
+unlock:
        uart_port_unlock_irqrestore(port, flags);
 
 out:
@@ -60,6 +64,11 @@ static int serial_port_runtime_suspend(struct device *dev)
                return 0;
 
        uart_port_lock_irqsave(port, &flags);
+       if (!port_dev->tx_enabled) {
+               uart_port_unlock_irqrestore(port, flags);
+               return 0;
+       }
+
        busy = __serial_port_busy(port);
        if (busy)
                port->ops->start_tx(port);
@@ -71,6 +80,31 @@ static int serial_port_runtime_suspend(struct device *dev)
        return busy ? -EBUSY : 0;
 }
 
+static void serial_base_port_set_tx(struct uart_port *port,
+                                   struct serial_port_device *port_dev,
+                                   bool enabled)
+{
+       unsigned long flags;
+
+       uart_port_lock_irqsave(port, &flags);
+       port_dev->tx_enabled = enabled;
+       uart_port_unlock_irqrestore(port, flags);
+}
+
+void serial_base_port_startup(struct uart_port *port)
+{
+       struct serial_port_device *port_dev = port->port_dev;
+
+       serial_base_port_set_tx(port, port_dev, true);
+}
+
+void serial_base_port_shutdown(struct uart_port *port)
+{
+       struct serial_port_device *port_dev = port->port_dev;
+
+       serial_base_port_set_tx(port, port_dev, false);
+}
+
 static DEFINE_RUNTIME_DEV_PM_OPS(serial_port_pm,
                                 serial_port_runtime_suspend,
                                 serial_port_runtime_resume, NULL);
index 58d169e5c1db03b910686ac2a229116644f0d6e9..4fa5a03ebac08e4dbc9a85e6e54b0930595fa0ed 100644 (file)
@@ -861,6 +861,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
        const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
        u32 sr;
        unsigned int size;
+       irqreturn_t ret = IRQ_NONE;
 
        sr = readl_relaxed(port->membase + ofs->isr);
 
@@ -869,11 +870,14 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
            (sr & USART_SR_TC)) {
                stm32_usart_tc_interrupt_disable(port);
                stm32_usart_rs485_rts_disable(port);
+               ret = IRQ_HANDLED;
        }
 
-       if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG)
+       if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG) {
                writel_relaxed(USART_ICR_RTOCF,
                               port->membase + ofs->icr);
+               ret = IRQ_HANDLED;
+       }
 
        if ((sr & USART_SR_WUF) && ofs->icr != UNDEF_REG) {
                /* Clear wake up flag and disable wake up interrupt */
@@ -882,6 +886,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
                stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE);
                if (irqd_is_wakeup_set(irq_get_irq_data(port->irq)))
                        pm_wakeup_event(tport->tty->dev, 0);
+               ret = IRQ_HANDLED;
        }
 
        /*
@@ -896,6 +901,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
                        uart_unlock_and_check_sysrq(port);
                        if (size)
                                tty_flip_buffer_push(tport);
+                       ret = IRQ_HANDLED;
                }
        }
 
@@ -903,6 +909,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
                uart_port_lock(port);
                stm32_usart_transmit_chars(port);
                uart_port_unlock(port);
+               ret = IRQ_HANDLED;
        }
 
        /* Receiver timeout irq for DMA RX */
@@ -912,9 +919,10 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
                uart_unlock_and_check_sysrq(port);
                if (size)
                        tty_flip_buffer_push(tport);
+               ret = IRQ_HANDLED;
        }
 
-       return IRQ_HANDLED;
+       return ret;
 }
 
 static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl)
@@ -1084,6 +1092,7 @@ static int stm32_usart_startup(struct uart_port *port)
                val |= USART_CR2_SWAP;
                writel_relaxed(val, port->membase + ofs->cr2);
        }
+       stm32_port->throttled = false;
 
        /* RX FIFO Flush */
        if (ofs->rqr != UNDEF_REG)
index 06859e17b67b7777a08d7e5e33b1bfb972cdd6c3..7a00004bfd0361799f1a43be4cb8e9c35e414d9e 100644 (file)
@@ -47,7 +47,7 @@ enum {
        TSTBUS_MAX,
 };
 
-#define QCOM_UFS_MAX_GEAR 4
+#define QCOM_UFS_MAX_GEAR 5
 #define QCOM_UFS_MAX_LANE 2
 
 enum {
@@ -67,26 +67,32 @@ static const struct __ufs_qcom_bw_table {
        [MODE_PWM][UFS_PWM_G2][UFS_LANE_1] = { 1844,            1000 },
        [MODE_PWM][UFS_PWM_G3][UFS_LANE_1] = { 3688,            1000 },
        [MODE_PWM][UFS_PWM_G4][UFS_LANE_1] = { 7376,            1000 },
+       [MODE_PWM][UFS_PWM_G5][UFS_LANE_1] = { 14752,           1000 },
        [MODE_PWM][UFS_PWM_G1][UFS_LANE_2] = { 1844,            1000 },
        [MODE_PWM][UFS_PWM_G2][UFS_LANE_2] = { 3688,            1000 },
        [MODE_PWM][UFS_PWM_G3][UFS_LANE_2] = { 7376,            1000 },
        [MODE_PWM][UFS_PWM_G4][UFS_LANE_2] = { 14752,           1000 },
+       [MODE_PWM][UFS_PWM_G5][UFS_LANE_2] = { 29504,           1000 },
        [MODE_HS_RA][UFS_HS_G1][UFS_LANE_1] = { 127796,         1000 },
        [MODE_HS_RA][UFS_HS_G2][UFS_LANE_1] = { 255591,         1000 },
        [MODE_HS_RA][UFS_HS_G3][UFS_LANE_1] = { 1492582,        102400 },
        [MODE_HS_RA][UFS_HS_G4][UFS_LANE_1] = { 2915200,        204800 },
+       [MODE_HS_RA][UFS_HS_G5][UFS_LANE_1] = { 5836800,        409600 },
        [MODE_HS_RA][UFS_HS_G1][UFS_LANE_2] = { 255591,         1000 },
        [MODE_HS_RA][UFS_HS_G2][UFS_LANE_2] = { 511181,         1000 },
        [MODE_HS_RA][UFS_HS_G3][UFS_LANE_2] = { 1492582,        204800 },
        [MODE_HS_RA][UFS_HS_G4][UFS_LANE_2] = { 2915200,        409600 },
+       [MODE_HS_RA][UFS_HS_G5][UFS_LANE_2] = { 5836800,        819200 },
        [MODE_HS_RB][UFS_HS_G1][UFS_LANE_1] = { 149422,         1000 },
        [MODE_HS_RB][UFS_HS_G2][UFS_LANE_1] = { 298189,         1000 },
        [MODE_HS_RB][UFS_HS_G3][UFS_LANE_1] = { 1492582,        102400 },
        [MODE_HS_RB][UFS_HS_G4][UFS_LANE_1] = { 2915200,        204800 },
+       [MODE_HS_RB][UFS_HS_G5][UFS_LANE_1] = { 5836800,        409600 },
        [MODE_HS_RB][UFS_HS_G1][UFS_LANE_2] = { 298189,         1000 },
        [MODE_HS_RB][UFS_HS_G2][UFS_LANE_2] = { 596378,         1000 },
        [MODE_HS_RB][UFS_HS_G3][UFS_LANE_2] = { 1492582,        204800 },
        [MODE_HS_RB][UFS_HS_G4][UFS_LANE_2] = { 2915200,        409600 },
+       [MODE_HS_RB][UFS_HS_G5][UFS_LANE_2] = { 5836800,        819200 },
        [MODE_MAX][0][0]                    = { 7643136,        307200 },
 };
 
index c8262e2f291778c785193b4311ab9613d0c18697..c553decb5461078280b5f566a6ccd4035727c4a6 100644 (file)
@@ -485,7 +485,6 @@ out_free_mem:
 static int service_outstanding_interrupt(struct wdm_device *desc)
 {
        int rv = 0;
-       int used;
 
        /* submit read urb only if the device is waiting for it */
        if (!desc->resp_count || !--desc->resp_count)
@@ -500,10 +499,7 @@ static int service_outstanding_interrupt(struct wdm_device *desc)
                goto out;
        }
 
-       used = test_and_set_bit(WDM_RESPONDING, &desc->flags);
-       if (used)
-               goto out;
-
+       set_bit(WDM_RESPONDING, &desc->flags);
        spin_unlock_irq(&desc->iuspin);
        rv = usb_submit_urb(desc->response, GFP_KERNEL);
        spin_lock_irq(&desc->iuspin);
index 9446660e231bb3f9a79b5cdf1503b13377539227..008053039875a4c6d3fc9b8822491c97eadd0abe 100644 (file)
@@ -5110,9 +5110,10 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
        }
        if (usb_endpoint_maxp(&udev->ep0.desc) == i) {
                ;       /* Initial ep0 maxpacket guess is right */
-       } else if ((udev->speed == USB_SPEED_FULL ||
+       } else if (((udev->speed == USB_SPEED_FULL ||
                                udev->speed == USB_SPEED_HIGH) &&
-                       (i == 8 || i == 16 || i == 32 || i == 64)) {
+                       (i == 8 || i == 16 || i == 32 || i == 64)) ||
+                       (udev->speed >= USB_SPEED_SUPER && i > 0)) {
                /* Initial guess is wrong; use the descriptor's value */
                if (udev->speed == USB_SPEED_FULL)
                        dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
index 686c01af03e63aa52253be6c44371ac335eb8fcd..e7da2fca11a48cf9c3d53cd53d124d65a1cd751f 100644 (file)
@@ -51,13 +51,15 @@ static ssize_t disable_show(struct device *dev,
        struct usb_port *port_dev = to_usb_port(dev);
        struct usb_device *hdev = to_usb_device(dev->parent->parent);
        struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
-       struct usb_interface *intf = to_usb_interface(hub->intfdev);
+       struct usb_interface *intf = to_usb_interface(dev->parent);
        int port1 = port_dev->portnum;
        u16 portstatus, unused;
        bool disabled;
        int rc;
        struct kernfs_node *kn;
 
+       if (!hub)
+               return -ENODEV;
        hub_get(hub);
        rc = usb_autopm_get_interface(intf);
        if (rc < 0)
@@ -101,12 +103,14 @@ static ssize_t disable_store(struct device *dev, struct device_attribute *attr,
        struct usb_port *port_dev = to_usb_port(dev);
        struct usb_device *hdev = to_usb_device(dev->parent->parent);
        struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
-       struct usb_interface *intf = to_usb_interface(hub->intfdev);
+       struct usb_interface *intf = to_usb_interface(dev->parent);
        int port1 = port_dev->portnum;
        bool disabled;
        int rc;
        struct kernfs_node *kn;
 
+       if (!hub)
+               return -ENODEV;
        rc = kstrtobool(buf, &disabled);
        if (rc)
                return rc;
@@ -449,8 +453,10 @@ static void usb_port_shutdown(struct device *dev)
 {
        struct usb_port *port_dev = to_usb_port(dev);
 
-       if (port_dev->child)
+       if (port_dev->child) {
                usb_disable_usb2_hardware_lpm(port_dev->child);
+               usb_unlocked_disable_lpm(port_dev->child);
+       }
 }
 
 static const struct dev_pm_ops usb_port_pm_ops = {
index 79582b102c7eda2eb72f6da3c293615cdad50b56..994a78ad084b1c485673ca3c88819d4e752ef2ee 100644 (file)
@@ -867,13 +867,15 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
        struct dwc2_dma_desc *dma_desc;
        struct dwc2_hcd_iso_packet_desc *frame_desc;
        u16 frame_desc_idx;
-       struct urb *usb_urb = qtd->urb->priv;
+       struct urb *usb_urb;
        u16 remain = 0;
        int rc = 0;
 
        if (!qtd->urb)
                return -EINVAL;
 
+       usb_urb = qtd->urb->priv;
+
        dma_sync_single_for_cpu(hsotg->dev, qh->desc_list_dma + (idx *
                                sizeof(struct dwc2_dma_desc)),
                                sizeof(struct dwc2_dma_desc),
index 31684cdaaae3056c6cf9b16d31cc0eb4f217b7bb..100041320e8dd2e80488b7dfdc372d373ea0d251 100644 (file)
@@ -104,6 +104,27 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc)
        return 0;
 }
 
+void dwc3_enable_susphy(struct dwc3 *dwc, bool enable)
+{
+       u32 reg;
+
+       reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
+       if (enable && !dwc->dis_u3_susphy_quirk)
+               reg |= DWC3_GUSB3PIPECTL_SUSPHY;
+       else
+               reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
+
+       dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
+
+       reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+       if (enable && !dwc->dis_u2_susphy_quirk)
+               reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+       else
+               reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+
+       dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+}
+
 void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
 {
        u32 reg;
@@ -585,11 +606,8 @@ static int dwc3_core_ulpi_init(struct dwc3 *dwc)
  */
 static int dwc3_phy_setup(struct dwc3 *dwc)
 {
-       unsigned int hw_mode;
        u32 reg;
 
-       hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
-
        reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
 
        /*
@@ -599,21 +617,16 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
        reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX;
 
        /*
-        * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
-        * to '0' during coreConsultant configuration. So default value
-        * will be '0' when the core is reset. Application needs to set it
-        * to '1' after the core initialization is completed.
-        */
-       if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A))
-               reg |= DWC3_GUSB3PIPECTL_SUSPHY;
-
-       /*
-        * For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be cleared after
-        * power-on reset, and it can be set after core initialization, which is
-        * after device soft-reset during initialization.
+        * Above DWC_usb3.0 1.94a, it is recommended to set
+        * DWC3_GUSB3PIPECTL_SUSPHY to '0' during coreConsultant configuration.
+        * So default value will be '0' when the core is reset. Application
+        * needs to set it to '1' after the core initialization is completed.
+        *
+        * Similarly for DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be
+        * cleared after power-on reset, and it can be set after core
+        * initialization.
         */
-       if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
-               reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
+       reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
 
        if (dwc->u2ss_inp3_quirk)
                reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
@@ -639,9 +652,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
        if (dwc->tx_de_emphasis_quirk)
                reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
 
-       if (dwc->dis_u3_susphy_quirk)
-               reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
-
        if (dwc->dis_del_phy_power_chg_quirk)
                reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
 
@@ -689,24 +699,15 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
        }
 
        /*
-        * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
-        * '0' during coreConsultant configuration. So default value will
-        * be '0' when the core is reset. Application needs to set it to
-        * '1' after the core initialization is completed.
-        */
-       if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A))
-               reg |= DWC3_GUSB2PHYCFG_SUSPHY;
-
-       /*
-        * For DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared after
-        * power-on reset, and it can be set after core initialization, which is
-        * after device soft-reset during initialization.
+        * Above DWC_usb3.0 1.94a, it is recommended to set
+        * DWC3_GUSB2PHYCFG_SUSPHY to '0' during coreConsultant configuration.
+        * So default value will be '0' when the core is reset. Application
+        * needs to set it to '1' after the core initialization is completed.
+        *
+        * Similarly for DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared
+        * after power-on reset, and it can be set after core initialization.
         */
-       if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
-               reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
-
-       if (dwc->dis_u2_susphy_quirk)
-               reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+       reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
 
        if (dwc->dis_enblslpm_quirk)
                reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
@@ -1227,21 +1228,6 @@ static int dwc3_core_init(struct dwc3 *dwc)
        if (ret)
                goto err_exit_phy;
 
-       if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD &&
-           !DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) {
-               if (!dwc->dis_u3_susphy_quirk) {
-                       reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
-                       reg |= DWC3_GUSB3PIPECTL_SUSPHY;
-                       dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
-               }
-
-               if (!dwc->dis_u2_susphy_quirk) {
-                       reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
-                       reg |= DWC3_GUSB2PHYCFG_SUSPHY;
-                       dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
-               }
-       }
-
        dwc3_core_setup_global_control(dwc);
        dwc3_core_num_eps(dwc);
 
index 7e80dd3d466b88538f597a5f1534fd020ac23763..180dd8d29287c6851581e0a0d194a8c79c0959c2 100644 (file)
@@ -1580,6 +1580,7 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc);
 void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
 
 int dwc3_core_soft_reset(struct dwc3 *dwc);
+void dwc3_enable_susphy(struct dwc3 *dwc, bool enable);
 
 #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
 int dwc3_host_init(struct dwc3 *dwc);
index 72bb722da2f258fb07fa7701bbe07b7509f1c15a..d96ffbe520397ad1a66ff661a01530ce017de9f3 100644 (file)
@@ -226,7 +226,8 @@ void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
 
        /* reinitialize physical ep1 */
        dep = dwc->eps[1];
-       dep->flags = DWC3_EP_ENABLED;
+       dep->flags &= DWC3_EP_RESOURCE_ALLOCATED;
+       dep->flags |= DWC3_EP_ENABLED;
 
        /* stall is always issued on EP0 */
        dep = dwc->eps[0];
index 4df2661f66751bd56a3717d9f0d2705a29f07738..f94f68f1e7d2b7ccab8f565048a41950a34aa464 100644 (file)
@@ -2924,6 +2924,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
        dwc3_ep0_out_start(dwc);
 
        dwc3_gadget_enable_irq(dwc);
+       dwc3_enable_susphy(dwc, true);
 
        return 0;
 
@@ -4690,6 +4691,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
        if (!dwc->gadget)
                return;
 
+       dwc3_enable_susphy(dwc, false);
        usb_del_gadget(dwc->gadget);
        dwc3_gadget_free_endpoints(dwc);
        usb_put_gadget(dwc->gadget);
index 0204787df81d50b9291b1701c554795c3d97bca8..a171b27a7845af9ceb92d567d380a540e3ad0ef8 100644 (file)
 #include <linux/irq.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
 
 #include "../host/xhci-port.h"
 #include "../host/xhci-ext-caps.h"
 #include "../host/xhci-caps.h"
+#include "../host/xhci-plat.h"
 #include "core.h"
 
 #define XHCI_HCSPARAMS1                0x4
@@ -57,6 +60,24 @@ static void dwc3_power_off_all_roothub_ports(struct dwc3 *dwc)
        }
 }
 
+static void dwc3_xhci_plat_start(struct usb_hcd *hcd)
+{
+       struct platform_device *pdev;
+       struct dwc3 *dwc;
+
+       if (!usb_hcd_is_primary_hcd(hcd))
+               return;
+
+       pdev = to_platform_device(hcd->self.controller);
+       dwc = dev_get_drvdata(pdev->dev.parent);
+
+       dwc3_enable_susphy(dwc, true);
+}
+
+static const struct xhci_plat_priv dwc3_xhci_plat_quirk = {
+       .plat_start = dwc3_xhci_plat_start,
+};
+
 static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc,
                                        int irq, char *name)
 {
@@ -167,6 +188,11 @@ int dwc3_host_init(struct dwc3 *dwc)
                }
        }
 
+       ret = platform_device_add_data(xhci, &dwc3_xhci_plat_quirk,
+                                      sizeof(struct xhci_plat_priv));
+       if (ret)
+               goto err;
+
        ret = platform_device_add(xhci);
        if (ret) {
                dev_err(dwc->dev, "failed to register xHCI device\n");
@@ -192,6 +218,7 @@ void dwc3_host_exit(struct dwc3 *dwc)
        if (dwc->sys_wakeup)
                device_init_wakeup(&dwc->xhci->dev, false);
 
+       dwc3_enable_susphy(dwc, false);
        platform_device_unregister(dwc->xhci);
        dwc->xhci = NULL;
 }
index 0ace45b66a31c417f7e6da9f811c3d8b5c736246..0e151b54aae82a3677dbbd0487d91e403f83e7b5 100644 (file)
@@ -2112,7 +2112,7 @@ unknown:
                        buf[5] = 0x01;
                        switch (ctrl->bRequestType & USB_RECIP_MASK) {
                        case USB_RECIP_DEVICE:
-                               if (w_index != 0x4 || (w_value >> 8))
+                               if (w_index != 0x4 || (w_value & 0xff))
                                        break;
                                buf[6] = w_index;
                                /* Number of ext compat interfaces */
@@ -2128,9 +2128,9 @@ unknown:
                                }
                                break;
                        case USB_RECIP_INTERFACE:
-                               if (w_index != 0x5 || (w_value >> 8))
+                               if (w_index != 0x5 || (w_value & 0xff))
                                        break;
-                               interface = w_value & 0xFF;
+                               interface = w_value >> 8;
                                if (interface >= MAX_CONFIG_INTERFACES ||
                                    !os_desc_cfg->interface[interface])
                                        break;
index bffbc1dc651f9ecdead7e3398004ca2e77355cef..a057cbedf3c9b30430eeb3a8749975e58cec54da 100644 (file)
@@ -46,6 +46,8 @@
 
 #define FUNCTIONFS_MAGIC       0xa647361 /* Chosen by a honest dice roll ;) */
 
+#define DMABUF_ENQUEUE_TIMEOUT_MS 5000
+
 MODULE_IMPORT_NS(DMA_BUF);
 
 /* Reference counter handling */
@@ -850,6 +852,7 @@ static void ffs_user_copy_worker(struct work_struct *work)
                                                   work);
        int ret = io_data->status;
        bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
+       unsigned long flags;
 
        if (io_data->read && ret > 0) {
                kthread_use_mm(io_data->mm);
@@ -862,6 +865,11 @@ static void ffs_user_copy_worker(struct work_struct *work)
        if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd)
                eventfd_signal(io_data->ffs->ffs_eventfd);
 
+       spin_lock_irqsave(&io_data->ffs->eps_lock, flags);
+       usb_ep_free_request(io_data->ep, io_data->req);
+       io_data->req = NULL;
+       spin_unlock_irqrestore(&io_data->ffs->eps_lock, flags);
+
        if (io_data->read)
                kfree(io_data->to_free);
        ffs_free_buffer(io_data);
@@ -875,7 +883,6 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
        struct ffs_data *ffs = io_data->ffs;
 
        io_data->status = req->status ? req->status : req->actual;
-       usb_ep_free_request(_ep, req);
 
        INIT_WORK(&io_data->work, ffs_user_copy_worker);
        queue_work(ffs->io_completion_wq, &io_data->work);
@@ -1578,10 +1585,13 @@ static int ffs_dmabuf_transfer(struct file *file,
        struct ffs_dmabuf_priv *priv;
        struct ffs_dma_fence *fence;
        struct usb_request *usb_req;
+       enum dma_resv_usage resv_dir;
        struct dma_buf *dmabuf;
+       unsigned long timeout;
        struct ffs_ep *ep;
        bool cookie;
        u32 seqno;
+       long retl;
        int ret;
 
        if (req->flags & ~USB_FFS_DMABUF_TRANSFER_MASK)
@@ -1615,17 +1625,14 @@ static int ffs_dmabuf_transfer(struct file *file,
                goto err_attachment_put;
 
        /* Make sure we don't have writers */
-       if (!dma_resv_test_signaled(dmabuf->resv, DMA_RESV_USAGE_WRITE)) {
-               pr_vdebug("FFS WRITE fence is not signaled\n");
-               ret = -EBUSY;
-               goto err_resv_unlock;
-       }
-
-       /* If we're writing to the DMABUF, make sure we don't have readers */
-       if (epfile->in &&
-           !dma_resv_test_signaled(dmabuf->resv, DMA_RESV_USAGE_READ)) {
-               pr_vdebug("FFS READ fence is not signaled\n");
-               ret = -EBUSY;
+       timeout = nonblock ? 0 : msecs_to_jiffies(DMABUF_ENQUEUE_TIMEOUT_MS);
+       retl = dma_resv_wait_timeout(dmabuf->resv,
+                                    dma_resv_usage_rw(epfile->in),
+                                    true, timeout);
+       if (retl == 0)
+               retl = -EBUSY;
+       if (retl < 0) {
+               ret = (int)retl;
                goto err_resv_unlock;
        }
 
@@ -1665,8 +1672,9 @@ static int ffs_dmabuf_transfer(struct file *file,
        dma_fence_init(&fence->base, &ffs_dmabuf_fence_ops,
                       &priv->lock, priv->context, seqno);
 
-       dma_resv_add_fence(dmabuf->resv, &fence->base,
-                          dma_resv_usage_rw(epfile->in));
+       resv_dir = epfile->in ? DMA_RESV_USAGE_WRITE : DMA_RESV_USAGE_READ;
+
+       dma_resv_add_fence(dmabuf->resv, &fence->base, resv_dir);
        dma_resv_unlock(dmabuf->resv);
 
        /* Now that the dma_fence is in place, queue the transfer. */
@@ -3803,7 +3811,7 @@ static int ffs_func_setup(struct usb_function *f,
        __ffs_event_add(ffs, FUNCTIONFS_SETUP);
        spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
 
-       return creq->wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0;
+       return ffs->ev.setup.wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0;
 }
 
 static bool ffs_func_req_match(struct usb_function *f,
index 28f4e6552e84592566d261ec3174773650c5d444..0acc32ed99609f8166877bd221087211e90b119d 100644 (file)
@@ -878,7 +878,7 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                if (alt > 1)
                        goto fail;
 
-               if (ncm->port.in_ep->enabled) {
+               if (ncm->netdev) {
                        DBG(cdev, "reset ncm\n");
                        ncm->netdev = NULL;
                        gether_disconnect(&ncm->port);
@@ -1367,7 +1367,7 @@ static void ncm_disable(struct usb_function *f)
 
        DBG(cdev, "ncm deactivated\n");
 
-       if (ncm->port.in_ep->enabled) {
+       if (ncm->netdev) {
                ncm->netdev = NULL;
                gether_disconnect(&ncm->port);
        }
index 7e704b2bcfd1ce5a2c28a4f318fca6633a7072f8..a4377df612f51e12760195cd1fbe89ec9c541fbe 100644 (file)
@@ -92,10 +92,10 @@ static int __uvcg_iter_item_entries(const char *page, size_t len,
 
        while (pg - page < len) {
                i = 0;
-               while (i < sizeof(buf) && (pg - page < len) &&
+               while (i < bufsize && (pg - page < len) &&
                       *pg != '\0' && *pg != '\n')
                        buf[i++] = *pg++;
-               if (i == sizeof(buf)) {
+               if (i == bufsize) {
                        ret = -EINVAL;
                        goto out_free_buf;
                }
index e82d03224f940f9a98f978f7b46241f98f1c8e3e..3432ebfae978794fa88b60811bbaedfbc0822bb8 100644 (file)
@@ -868,7 +868,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 {
        struct fsl_ep *ep = container_of(_ep, struct fsl_ep, ep);
        struct fsl_req *req = container_of(_req, struct fsl_req, req);
-       struct fsl_udc *udc;
+       struct fsl_udc *udc = ep->udc;
        unsigned long flags;
        int ret;
 
@@ -878,7 +878,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
                dev_vdbg(&udc->gadget.dev, "%s, bad params\n", __func__);
                return -EINVAL;
        }
-       if (unlikely(!_ep || !ep->ep.desc)) {
+       if (unlikely(!ep->ep.desc)) {
                dev_vdbg(&udc->gadget.dev, "%s, bad ep\n", __func__);
                return -EINVAL;
        }
@@ -887,7 +887,6 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
                        return -EMSGSIZE;
        }
 
-       udc = ep->udc;
        if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
                return -ESHUTDOWN;
 
index 4f9982ecfb583e60e0f5b9cfff4c8001b2bf598f..5cec7640e913c8bac477f67c517304bb0afe5941 100644 (file)
@@ -888,6 +888,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
        /* Check for an all 1's result which is a typical consequence
         * of dead, unclocked, or unplugged (CardBus...) devices
         */
+again:
        if (ints == ~(u32)0) {
                ohci->rh_state = OHCI_RH_HALTED;
                ohci_dbg (ohci, "device removed!\n");
@@ -982,6 +983,13 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
        }
        spin_unlock(&ohci->lock);
 
+       /* repeat until all enabled interrupts are handled */
+       if (ohci->rh_state != OHCI_RH_HALTED) {
+               ints = ohci_readl(ohci, &regs->intrstatus);
+               if (ints && (ints & ohci_readl(ohci, &regs->intrenable)))
+                       goto again;
+       }
+
        return IRQ_HANDLED;
 }
 
index 2d15386f2c504b7aa8b1798f1b41b1e81b1498c1..6475130eac4b38061ea038ad14b00a48f269d4e0 100644 (file)
@@ -8,7 +8,9 @@
 #ifndef _XHCI_PLAT_H
 #define _XHCI_PLAT_H
 
-#include "xhci.h"      /* for hcd_to_xhci() */
+struct device;
+struct platform_device;
+struct usb_hcd;
 
 struct xhci_plat_priv {
        const char *firmware_name;
index 52278afea94be01b9f05c71fffaca9d3da98c936..575f0fd9c9f11e3df95220dfc4be8bb62ea9fc54 100644 (file)
@@ -3133,7 +3133,7 @@ static int xhci_handle_events(struct xhci_hcd *xhci, struct xhci_interrupter *ir
 irqreturn_t xhci_irq(struct usb_hcd *hcd)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-       irqreturn_t ret = IRQ_NONE;
+       irqreturn_t ret = IRQ_HANDLED;
        u32 status;
 
        spin_lock(&xhci->lock);
@@ -3141,12 +3141,13 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
        status = readl(&xhci->op_regs->status);
        if (status == ~(u32)0) {
                xhci_hc_died(xhci);
-               ret = IRQ_HANDLED;
                goto out;
        }
 
-       if (!(status & STS_EINT))
+       if (!(status & STS_EINT)) {
+               ret = IRQ_NONE;
                goto out;
+       }
 
        if (status & STS_HCE) {
                xhci_warn(xhci, "WARNING: Host Controller Error\n");
@@ -3156,7 +3157,6 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
        if (status & STS_FATAL) {
                xhci_warn(xhci, "WARNING: Host System Error\n");
                xhci_halt(xhci);
-               ret = IRQ_HANDLED;
                goto out;
        }
 
@@ -3167,7 +3167,6 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
         */
        status |= STS_EINT;
        writel(status, &xhci->op_regs->status);
-       ret = IRQ_HANDLED;
 
        /* This is the handler of the primary interrupter */
        xhci_handle_events(xhci, xhci->interrupters[0]);
index ec65b24eafa868dafe6bafaf1c3c27b16550f31d..4f59867d7117cfda924d151e35b8faeb13dd0bec 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <linux/usb/rzv2m_usb3drd.h>
+#include "xhci.h"
 #include "xhci-plat.h"
 #include "xhci-rzv2m.h"
 
index 1740000d54c295d4d8884910fc3f3ae04e6a4d6b..5762564b9d73375f6e65ccd05bc9b583f6abaa6f 100644 (file)
@@ -172,8 +172,7 @@ DECLARE_EVENT_CLASS(xhci_log_free_virt_dev,
                __field(void *, vdev)
                __field(unsigned long long, out_ctx)
                __field(unsigned long long, in_ctx)
-               __field(int, hcd_portnum)
-               __field(int, hw_portnum)
+               __field(int, slot_id)
                __field(u16, current_mel)
 
        ),
@@ -181,13 +180,12 @@ DECLARE_EVENT_CLASS(xhci_log_free_virt_dev,
                __entry->vdev = vdev;
                __entry->in_ctx = (unsigned long long) vdev->in_ctx->dma;
                __entry->out_ctx = (unsigned long long) vdev->out_ctx->dma;
-               __entry->hcd_portnum = (int) vdev->rhub_port->hcd_portnum;
-               __entry->hw_portnum = (int) vdev->rhub_port->hw_portnum;
+               __entry->slot_id = (int) vdev->slot_id;
                __entry->current_mel = (u16) vdev->current_mel;
                ),
-       TP_printk("vdev %p ctx %llx | %llx hcd_portnum %d hw_portnum %d current_mel %d",
-               __entry->vdev, __entry->in_ctx, __entry->out_ctx,
-               __entry->hcd_portnum, __entry->hw_portnum, __entry->current_mel
+       TP_printk("vdev %p slot %d ctx %llx | %llx current_mel %d",
+               __entry->vdev, __entry->slot_id, __entry->in_ctx,
+               __entry->out_ctx, __entry->current_mel
        )
 );
 
index c6101ed2d9d49a3d556b0175ed72cdb1a9cf9193..d8049275a023c61c005cd7a8a89e0bb335d062a8 100644 (file)
@@ -78,7 +78,7 @@ static int onboard_hub_power_on(struct onboard_hub *hub)
        err = regulator_bulk_enable(hub->pdata->num_supplies, hub->supplies);
        if (err) {
                dev_err(hub->dev, "failed to enable supplies: %pe\n", ERR_PTR(err));
-               return err;
+               goto disable_clk;
        }
 
        fsleep(hub->pdata->reset_us);
@@ -87,6 +87,10 @@ static int onboard_hub_power_on(struct onboard_hub *hub)
        hub->is_powered_on = true;
 
        return 0;
+
+disable_clk:
+       clk_disable_unprepare(hub->clk);
+       return err;
 }
 
 static int onboard_hub_power_off(struct onboard_hub *hub)
index 55a65d941ccbfb1161d363ac72881ce0f490a8df..8a5846d4adf67e1de41ff8fa1b5ed28c1efcc960 100644 (file)
@@ -255,6 +255,10 @@ static void option_instat_callback(struct urb *urb);
 #define QUECTEL_PRODUCT_EM061K_LMS             0x0124
 #define QUECTEL_PRODUCT_EC25                   0x0125
 #define QUECTEL_PRODUCT_EM060K_128             0x0128
+#define QUECTEL_PRODUCT_EM060K_129             0x0129
+#define QUECTEL_PRODUCT_EM060K_12a             0x012a
+#define QUECTEL_PRODUCT_EM060K_12b             0x012b
+#define QUECTEL_PRODUCT_EM060K_12c             0x012c
 #define QUECTEL_PRODUCT_EG91                   0x0191
 #define QUECTEL_PRODUCT_EG95                   0x0195
 #define QUECTEL_PRODUCT_BG96                   0x0296
@@ -1218,6 +1222,18 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x30) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0x00, 0x40) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x40) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_129, 0xff, 0xff, 0x30) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_129, 0xff, 0x00, 0x40) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_129, 0xff, 0xff, 0x40) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12a, 0xff, 0xff, 0x30) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12a, 0xff, 0x00, 0x40) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12a, 0xff, 0xff, 0x40) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12b, 0xff, 0xff, 0x30) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12b, 0xff, 0x00, 0x40) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12b, 0xff, 0xff, 0x40) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12c, 0xff, 0xff, 0x30) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12c, 0xff, 0x00, 0x40) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12c, 0xff, 0xff, 0x40) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x30) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0x00, 0x40) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x40) },
@@ -1360,6 +1376,12 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = NCTRL(2) | RSVD(3) },
        { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1083, 0xff),    /* Telit FE990 (ECM) */
          .driver_info = NCTRL(0) | RSVD(1) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a0, 0xff),    /* Telit FN20C04 (rmnet) */
+         .driver_info = RSVD(0) | NCTRL(3) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a4, 0xff),    /* Telit FN20C04 (rmnet) */
+         .driver_info = RSVD(0) | NCTRL(3) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a9, 0xff),    /* Telit FN20C04 (rmnet) */
+         .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
          .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
@@ -2052,6 +2074,10 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = RSVD(3) },
        { USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, 0x9803, 0xff),
          .driver_info = RSVD(4) },
+       { USB_DEVICE(LONGCHEER_VENDOR_ID, 0x9b05),      /* Longsung U8300 */
+         .driver_info = RSVD(4) | RSVD(5) },
+       { USB_DEVICE(LONGCHEER_VENDOR_ID, 0x9b3c),      /* Longsung U9300 */
+         .driver_info = RSVD(0) | RSVD(4) },
        { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
        { USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) },
        { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
@@ -2272,15 +2298,29 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) },    /* Fibocom FG150 Diag */
        { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) },          /* Fibocom FG150 AT */
        { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0111, 0xff) },                   /* Fibocom FM160 (MBIM mode) */
+       { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0115, 0xff),                     /* Fibocom FM135 (laptop MBIM) */
+         .driver_info = RSVD(5) },
        { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) },                   /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */
        { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a2, 0xff) },                   /* Fibocom FM101-GL (laptop MBIM) */
        { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a3, 0xff) },                   /* Fibocom FM101-GL (laptop MBIM) */
        { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a4, 0xff),                     /* Fibocom FM101-GL (laptop MBIM) */
          .driver_info = RSVD(4) },
+       { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a04, 0xff) },                   /* Fibocom FM650-CN (ECM mode) */
+       { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a05, 0xff) },                   /* Fibocom FM650-CN (NCM mode) */
+       { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a06, 0xff) },                   /* Fibocom FM650-CN (RNDIS mode) */
+       { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a07, 0xff) },                   /* Fibocom FM650-CN (MBIM mode) */
        { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) },                   /* LongSung M5710 */
        { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) },                   /* GosunCn GM500 RNDIS */
        { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) },                   /* GosunCn GM500 MBIM */
        { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) },                   /* GosunCn GM500 ECM/NCM */
+       { USB_DEVICE(0x33f8, 0x0104),                                           /* Rolling RW101-GL (laptop RMNET) */
+         .driver_info = RSVD(4) | RSVD(5) },
+       { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a2, 0xff) },                   /* Rolling RW101-GL (laptop MBIM) */
+       { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a3, 0xff) },                   /* Rolling RW101-GL (laptop MBIM) */
+       { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a4, 0xff),                     /* Rolling RW101-GL (laptop MBIM) */
+         .driver_info = RSVD(4) },
+       { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0115, 0xff),                     /* Rolling RW135-GL (laptop MBIM) */
+         .driver_info = RSVD(5) },
        { USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) },
        { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) },
        { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) },
index 5535932e42cdeee1ffb84a47f2962c02bda1484a..4357cc67a8672224af8dd0a6b9bcb37e8ced790e 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/usb/typec_mux.h>
 
 #define IT5205_REG_CHIP_ID(x)  (0x4 + (x))
-#define IT5205FN_CHIP_ID       0x35323035 /* "5205" */
+#define IT5205FN_CHIP_ID       0x35303235 /* "5025" -> "5205" */
 
 /* MUX power down register */
 #define IT5205_REG_MUXPDR        0x10
index e48412cdcb0fb5b5562afb2ce65af38a1d31840c..d3958c061a972ccbde85c07595132793e80afc94 100644 (file)
@@ -104,14 +104,18 @@ static int qcom_pmic_typec_probe(struct platform_device *pdev)
 
        ret = tcpm->port_start(tcpm, tcpm->tcpm_port);
        if (ret)
-               goto fwnode_remove;
+               goto port_unregister;
 
        ret = tcpm->pdphy_start(tcpm, tcpm->tcpm_port);
        if (ret)
-               goto fwnode_remove;
+               goto port_stop;
 
        return 0;
 
+port_stop:
+       tcpm->port_stop(tcpm);
+port_unregister:
+       tcpm_unregister_port(tcpm->tcpm_port);
 fwnode_remove:
        fwnode_remove_software_node(tcpm->tcpc.fwnode);
 
index 6560f4fc98d5a3444ab33cc2ab29cd83890ac06b..5b7f52b74a40aa70096499e34d6c32a38c08fd48 100644 (file)
@@ -475,10 +475,8 @@ static int qcom_pmic_typec_pdphy_enable(struct pmic_typec_pdphy *pmic_typec_pdph
 
        qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy);
 done:
-       if (ret) {
-               regulator_disable(pmic_typec_pdphy->vdd_pdphy);
+       if (ret)
                dev_err(dev, "pdphy_enable fail %d\n", ret);
-       }
 
        return ret;
 }
@@ -524,12 +522,17 @@ static int qcom_pmic_typec_pdphy_start(struct pmic_typec *tcpm,
 
        ret = pmic_typec_pdphy_reset(pmic_typec_pdphy);
        if (ret)
-               return ret;
+               goto err_disable_vdd_pdhy;
 
        for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
                enable_irq(pmic_typec_pdphy->irq_data[i].irq);
 
        return 0;
+
+err_disable_vdd_pdhy:
+       regulator_disable(pmic_typec_pdphy->vdd_pdphy);
+
+       return ret;
 }
 
 static void qcom_pmic_typec_pdphy_stop(struct pmic_typec *tcpm)
index c26fb70c3ec6c09397ed4ac6c74300ac49fcc070..8a1af08f71b6450710e4ae7ff2e891f490a036ca 100644 (file)
@@ -1564,8 +1564,12 @@ static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header,
 static void tcpm_queue_vdm_unlocked(struct tcpm_port *port, const u32 header,
                                    const u32 *data, int cnt, enum tcpm_transmit_type tx_sop_type)
 {
+       if (port->state != SRC_READY && port->state != SNK_READY &&
+           port->state != SRC_VDM_IDENTITY_REQUEST)
+               return;
+
        mutex_lock(&port->lock);
-       tcpm_queue_vdm(port, header, data, cnt, TCPC_TX_SOP);
+       tcpm_queue_vdm(port, header, data, cnt, tx_sop_type);
        mutex_unlock(&port->lock);
 }
 
@@ -1580,7 +1584,8 @@ static void svdm_consume_identity(struct tcpm_port *port, const u32 *p, int cnt)
        port->partner_ident.cert_stat = p[VDO_INDEX_CSTAT];
        port->partner_ident.product = product;
 
-       typec_partner_set_identity(port->partner);
+       if (port->partner)
+               typec_partner_set_identity(port->partner);
 
        tcpm_log(port, "Identity: %04x:%04x.%04x",
                 PD_IDH_VID(vdo),
@@ -1742,6 +1747,9 @@ static void tcpm_register_partner_altmodes(struct tcpm_port *port)
        struct typec_altmode *altmode;
        int i;
 
+       if (!port->partner)
+               return;
+
        for (i = 0; i < modep->altmodes; i++) {
                altmode = typec_partner_register_altmode(port->partner,
                                                &modep->altmode_desc[i]);
@@ -2996,7 +3004,7 @@ static int tcpm_register_source_caps(struct tcpm_port *port)
 {
        struct usb_power_delivery_desc desc = { port->negotiated_rev };
        struct usb_power_delivery_capabilities_desc caps = { };
-       struct usb_power_delivery_capabilities *cap;
+       struct usb_power_delivery_capabilities *cap = port->partner_source_caps;
 
        if (!port->partner_pd)
                port->partner_pd = usb_power_delivery_register(NULL, &desc);
@@ -3006,6 +3014,9 @@ static int tcpm_register_source_caps(struct tcpm_port *port)
        memcpy(caps.pdo, port->source_caps, sizeof(u32) * port->nr_source_caps);
        caps.role = TYPEC_SOURCE;
 
+       if (cap)
+               usb_power_delivery_unregister_capabilities(cap);
+
        cap = usb_power_delivery_register_capabilities(port->partner_pd, &caps);
        if (IS_ERR(cap))
                return PTR_ERR(cap);
@@ -4231,7 +4242,10 @@ static int tcpm_init_vconn(struct tcpm_port *port)
 
 static void tcpm_typec_connect(struct tcpm_port *port)
 {
+       struct typec_partner *partner;
+
        if (!port->connected) {
+               port->connected = true;
                /* Make sure we don't report stale identity information */
                memset(&port->partner_ident, 0, sizeof(port->partner_ident));
                port->partner_desc.usb_pd = port->pd_capable;
@@ -4241,9 +4255,13 @@ static void tcpm_typec_connect(struct tcpm_port *port)
                        port->partner_desc.accessory = TYPEC_ACCESSORY_AUDIO;
                else
                        port->partner_desc.accessory = TYPEC_ACCESSORY_NONE;
-               port->partner = typec_register_partner(port->typec_port,
-                                                      &port->partner_desc);
-               port->connected = true;
+               partner = typec_register_partner(port->typec_port, &port->partner_desc);
+               if (IS_ERR(partner)) {
+                       dev_err(port->dev, "Failed to register partner (%ld)\n", PTR_ERR(partner));
+                       return;
+               }
+
+               port->partner = partner;
                typec_partner_set_usb_power_delivery(port->partner, port->partner_pd);
        }
 }
@@ -4323,9 +4341,11 @@ static void tcpm_typec_disconnect(struct tcpm_port *port)
        port->plug_prime = NULL;
        port->cable = NULL;
        if (port->connected) {
-               typec_partner_set_usb_power_delivery(port->partner, NULL);
-               typec_unregister_partner(port->partner);
-               port->partner = NULL;
+               if (port->partner) {
+                       typec_partner_set_usb_power_delivery(port->partner, NULL);
+                       typec_unregister_partner(port->partner);
+                       port->partner = NULL;
+               }
                port->connected = false;
        }
 }
@@ -4549,6 +4569,9 @@ static enum typec_cc_status tcpm_pwr_opmode_to_rp(enum typec_pwr_opmode opmode)
 
 static void tcpm_set_initial_svdm_version(struct tcpm_port *port)
 {
+       if (!port->partner)
+               return;
+
        switch (port->negotiated_rev) {
        case PD_REV30:
                break;
@@ -5605,6 +5628,7 @@ static void run_state_machine(struct tcpm_port *port)
                break;
        case PORT_RESET:
                tcpm_reset_port(port);
+               port->pd_events = 0;
                if (port->self_powered)
                        tcpm_set_cc(port, TYPEC_CC_OPEN);
                else
@@ -6855,14 +6879,14 @@ static int tcpm_pd_set(struct typec_port *p, struct usb_power_delivery *pd)
        if (data->sink_desc.pdo[0]) {
                for (i = 0; i < PDO_MAX_OBJECTS && data->sink_desc.pdo[i]; i++)
                        port->snk_pdo[i] = data->sink_desc.pdo[i];
-               port->nr_snk_pdo = i + 1;
+               port->nr_snk_pdo = i;
                port->operating_snk_mw = data->operating_snk_mw;
        }
 
        if (data->source_desc.pdo[0]) {
                for (i = 0; i < PDO_MAX_OBJECTS && data->source_desc.pdo[i]; i++)
                        port->src_pdo[i] = data->source_desc.pdo[i];
-               port->nr_src_pdo = i + 1;
+               port->nr_src_pdo = i;
        }
 
        switch (port->state) {
index 31d8a46ae5e7cb4c5fee6f7b663517a6c367d348..bd6ae92aa39e7a4e271894e79fe38a6e3b463444 100644 (file)
@@ -1736,11 +1736,13 @@ static int ucsi_init(struct ucsi *ucsi)
        ucsi->connector = connector;
        ucsi->ntfy = ntfy;
 
+       mutex_lock(&ucsi->ppm_lock);
        ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci));
+       mutex_unlock(&ucsi->ppm_lock);
        if (ret)
                return ret;
-       if (UCSI_CCI_CONNECTOR(READ_ONCE(cci)))
-               ucsi_connector_change(ucsi, cci);
+       if (UCSI_CCI_CONNECTOR(cci))
+               ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci));
 
        return 0;
 
index b246067e074bc0718ad49ad582b3ad9e382c9af0..6cb96a1e8b7df453c00ac0eaf9a568908f743c9f 100644 (file)
@@ -967,7 +967,7 @@ vdpa_dev_blk_seg_size_config_fill(struct sk_buff *msg, u64 features,
 
        val_u32 = __virtio32_to_cpu(true, config->size_max);
 
-       return nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_SEG_SIZE, val_u32);
+       return nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_SIZE_MAX, val_u32);
 }
 
 /* fill the block size*/
@@ -1089,7 +1089,7 @@ static int vdpa_dev_blk_ro_config_fill(struct sk_buff *msg, u64 features)
        u8 ro;
 
        ro = ((features & BIT_ULL(VIRTIO_BLK_F_RO)) == 0) ? 0 : 1;
-       if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_CFG_READ_ONLY, ro))
+       if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_READ_ONLY, ro))
                return -EMSGSIZE;
 
        return 0;
@@ -1100,7 +1100,7 @@ static int vdpa_dev_blk_flush_config_fill(struct sk_buff *msg, u64 features)
        u8 flush;
 
        flush = ((features & BIT_ULL(VIRTIO_BLK_F_FLUSH)) == 0) ? 0 : 1;
-       if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_CFG_FLUSH, flush))
+       if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_FLUSH, flush))
                return -EMSGSIZE;
 
        return 0;
index dae96c9f61cf8766cfe1e781f83c81e962691673..806ecd32219b691327d9620e41316404624a73ae 100644 (file)
@@ -196,7 +196,7 @@ err_mutex_unlock:
  */
 static vm_fault_t fb_deferred_io_page_mkwrite(struct fb_info *info, struct vm_fault *vmf)
 {
-       unsigned long offset = vmf->address - vmf->vma->vm_start;
+       unsigned long offset = vmf->pgoff << PAGE_SHIFT;
        struct page *page = vmf->page;
 
        file_update_time(vmf->vma->vm_file);
index b67a28da47026d0299b8a1f8c22a40fc36b1c4a2..a1c467a0e9f719665fc02fa559d5c94545e5725f 100644 (file)
@@ -68,7 +68,6 @@ out:
 static void vmgenid_notify(struct acpi_device *device, u32 event)
 {
        struct vmgenid_state *state = acpi_driver_data(device);
-       char *envp[] = { "NEW_VMGENID=1", NULL };
        u8 old_id[VMGENID_SIZE];
 
        memcpy(old_id, state->this_id, sizeof(old_id));
@@ -76,7 +75,6 @@ static void vmgenid_notify(struct acpi_device *device, u32 event)
        if (!memcmp(old_id, state->this_id, sizeof(old_id)))
                return;
        add_vmfork_randomness(state->this_id, sizeof(state->this_id));
-       kobject_uevent_env(&device->dev.kobj, KOBJ_CHANGE, envp);
 }
 
 static const struct acpi_device_id vmgenid_ids[] = {
index 29281b7c388703d6a6b809823198f37a9405241c..0d6138bee2a3d1ab565ab2d210c0a3f3bf97e4e3 100644 (file)
@@ -49,9 +49,6 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
 static inline void v9fs_fid_add_modes(struct p9_fid *fid, unsigned int s_flags,
        unsigned int s_cache, unsigned int f_flags)
 {
-       if (fid->qid.type != P9_QTFILE)
-               return;
-
        if ((!s_cache) ||
           ((fid->qid.version == 0) && !(s_flags & V9FS_IGNORE_QV)) ||
           (s_flags & V9FS_DIRECT_IO) || (f_flags & O_DIRECT)) {
index 9defa12208f98a715e5b894119f044fca50b3dc5..1775fcc7f0e8efa8b22f4c14e6886d85a22faeb5 100644 (file)
@@ -179,13 +179,14 @@ extern int v9fs_vfs_rename(struct mnt_idmap *idmap,
                           struct inode *old_dir, struct dentry *old_dentry,
                           struct inode *new_dir, struct dentry *new_dentry,
                           unsigned int flags);
-extern struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid);
+extern struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid,
+                                               bool new);
 extern const struct inode_operations v9fs_dir_inode_operations_dotl;
 extern const struct inode_operations v9fs_file_inode_operations_dotl;
 extern const struct inode_operations v9fs_symlink_inode_operations_dotl;
 extern const struct netfs_request_ops v9fs_req_ops;
 extern struct inode *v9fs_fid_iget_dotl(struct super_block *sb,
-                                       struct p9_fid *fid);
+                                               struct p9_fid *fid, bool new);
 
 /* other default globals */
 #define V9FS_PORT      564
@@ -224,12 +225,12 @@ static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses)
  */
 static inline struct inode *
 v9fs_get_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
-                       struct super_block *sb)
+                       struct super_block *sb, bool new)
 {
        if (v9fs_proto_dotl(v9ses))
-               return v9fs_fid_iget_dotl(sb, fid);
+               return v9fs_fid_iget_dotl(sb, fid, new);
        else
-               return v9fs_fid_iget(sb, fid);
+               return v9fs_fid_iget(sb, fid, new);
 }
 
 #endif
index abdbbaee51846218d807033a30c98394a0c213b6..348cc90bf9c56b7184dbac73faffe8d5f3d2762e 100644 (file)
@@ -520,6 +520,7 @@ const struct file_operations v9fs_file_operations = {
        .splice_read = v9fs_file_splice_read,
        .splice_write = iter_file_splice_write,
        .fsync = v9fs_file_fsync,
+       .setlease = simple_nosetlease,
 };
 
 const struct file_operations v9fs_file_operations_dotl = {
@@ -534,4 +535,5 @@ const struct file_operations v9fs_file_operations_dotl = {
        .splice_read = v9fs_file_splice_read,
        .splice_write = iter_file_splice_write,
        .fsync = v9fs_file_fsync_dotl,
+       .setlease = simple_nosetlease,
 };
index b01b1bbf24937168f6fdabe920ddbad0bae3e5d9..7a3308d776060e2e2565af09d358f2cf33416b6b 100644 (file)
@@ -83,7 +83,7 @@ static int p9mode2perm(struct v9fs_session_info *v9ses,
        int res;
        int mode = stat->mode;
 
-       res = mode & S_IALLUGO;
+       res = mode & 0777; /* S_IRWXUGO */
        if (v9fs_proto_dotu(v9ses)) {
                if ((mode & P9_DMSETUID) == P9_DMSETUID)
                        res |= S_ISUID;
@@ -178,6 +178,9 @@ int v9fs_uflags2omode(int uflags, int extended)
                break;
        }
 
+       if (uflags & O_TRUNC)
+               ret |= P9_OTRUNC;
+
        if (extended) {
                if (uflags & O_EXCL)
                        ret |= P9_OEXCL;
@@ -361,7 +364,8 @@ void v9fs_evict_inode(struct inode *inode)
                clear_inode(inode);
 }
 
-struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid)
+struct inode *
+v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid, bool new)
 {
        dev_t rdev;
        int retval;
@@ -373,8 +377,18 @@ struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid)
        inode = iget_locked(sb, QID2INO(&fid->qid));
        if (unlikely(!inode))
                return ERR_PTR(-ENOMEM);
-       if (!(inode->i_state & I_NEW))
-               return inode;
+       if (!(inode->i_state & I_NEW)) {
+               if (!new) {
+                       goto done;
+               } else {
+                       p9_debug(P9_DEBUG_VFS, "WARNING: Inode collision %ld\n",
+                                               inode->i_ino);
+                       iput(inode);
+                       remove_inode_hash(inode);
+                       inode = iget_locked(sb, QID2INO(&fid->qid));
+                       WARN_ON(!(inode->i_state & I_NEW));
+               }
+       }
 
        /*
         * initialize the inode with the stat info
@@ -398,11 +412,11 @@ struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid)
        v9fs_set_netfs_context(inode);
        v9fs_cache_inode_get_cookie(inode);
        unlock_new_inode(inode);
+done:
        return inode;
 error:
        iget_failed(inode);
        return ERR_PTR(retval);
-
 }
 
 /**
@@ -434,8 +448,15 @@ static int v9fs_at_to_dotl_flags(int flags)
  */
 static void v9fs_dec_count(struct inode *inode)
 {
-       if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2)
-               drop_nlink(inode);
+       if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2) {
+               if (inode->i_nlink) {
+                       drop_nlink(inode);
+               } else {
+                       p9_debug(P9_DEBUG_VFS,
+                                               "WARNING: unexpected i_nlink zero %d inode %ld\n",
+                                               inode->i_nlink, inode->i_ino);
+               }
+       }
 }
 
 /**
@@ -486,6 +507,9 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
                } else
                        v9fs_dec_count(inode);
 
+               if (inode->i_nlink <= 0)        /* no more refs unhash it */
+                       remove_inode_hash(inode);
+
                v9fs_invalidate_inode_attr(inode);
                v9fs_invalidate_inode_attr(dir);
 
@@ -551,7 +575,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
                /*
                 * instantiate inode and assign the unopened fid to the dentry
                 */
-               inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+               inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb, true);
                if (IS_ERR(inode)) {
                        err = PTR_ERR(inode);
                        p9_debug(P9_DEBUG_VFS,
@@ -680,7 +704,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
        else if (IS_ERR(fid))
                inode = ERR_CAST(fid);
        else
-               inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+               inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb, false);
        /*
         * If we had a rename on the server and a parallel lookup
         * for the new name, then make sure we instantiate with
@@ -1061,8 +1085,6 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
        struct v9fs_session_info *v9ses = sb->s_fs_info;
        struct v9fs_inode *v9inode = V9FS_I(inode);
 
-       set_nlink(inode, 1);
-
        inode_set_atime(inode, stat->atime, 0);
        inode_set_mtime(inode, stat->mtime, 0);
        inode_set_ctime(inode, stat->mtime, 0);
index 55dde186041a38d98c997e2ea728e2004c2a9606..c61b97bd13b9a7875b14f9af6e109b85143c79da 100644 (file)
@@ -52,7 +52,10 @@ static kgid_t v9fs_get_fsgid_for_create(struct inode *dir_inode)
        return current_fsgid();
 }
 
-struct inode *v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid)
+
+
+struct inode *
+v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid, bool new)
 {
        int retval;
        struct inode *inode;
@@ -62,8 +65,18 @@ struct inode *v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid)
        inode = iget_locked(sb, QID2INO(&fid->qid));
        if (unlikely(!inode))
                return ERR_PTR(-ENOMEM);
-       if (!(inode->i_state & I_NEW))
-               return inode;
+       if (!(inode->i_state & I_NEW)) {
+               if (!new) {
+                       goto done;
+               } else { /* deal with race condition in inode number reuse */
+                       p9_debug(P9_DEBUG_ERROR, "WARNING: Inode collision %lx\n",
+                                               inode->i_ino);
+                       iput(inode);
+                       remove_inode_hash(inode);
+                       inode = iget_locked(sb, QID2INO(&fid->qid));
+                       WARN_ON(!(inode->i_state & I_NEW));
+               }
+       }
 
        /*
         * initialize the inode with the stat info
@@ -90,12 +103,11 @@ struct inode *v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid)
                goto error;
 
        unlock_new_inode(inode);
-
+done:
        return inode;
 error:
        iget_failed(inode);
        return ERR_PTR(retval);
-
 }
 
 struct dotl_openflag_map {
@@ -247,7 +259,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
                p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
                goto out;
        }
-       inode = v9fs_fid_iget_dotl(dir->i_sb, fid);
+       inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err);
@@ -340,7 +352,7 @@ static int v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap,
        }
 
        /* instantiate inode and assign the unopened fid to the dentry */
-       inode = v9fs_fid_iget_dotl(dir->i_sb, fid);
+       inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n",
@@ -776,7 +788,7 @@ v9fs_vfs_mknod_dotl(struct mnt_idmap *idmap, struct inode *dir,
                         err);
                goto error;
        }
-       inode = v9fs_fid_iget_dotl(dir->i_sb, fid);
+       inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n",
index 4236058c7bbd18b726925e808e73bcb6c08edfeb..f52fdf42945cf15d21fe55f01da21967714ed07c 100644 (file)
@@ -139,7 +139,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
        else
                sb->s_d_op = &v9fs_dentry_operations;
 
-       inode = v9fs_get_inode_from_fid(v9ses, fid, sb);
+       inode = v9fs_get_inode_from_fid(v9ses, fid, sb, true);
        if (IS_ERR(inode)) {
                retval = PTR_ERR(inode);
                goto release_sb;
@@ -244,6 +244,21 @@ done:
        return res;
 }
 
+static int v9fs_drop_inode(struct inode *inode)
+{
+       struct v9fs_session_info *v9ses;
+
+       v9ses = v9fs_inode2v9ses(inode);
+       if (v9ses->cache & (CACHE_META|CACHE_LOOSE))
+               return generic_drop_inode(inode);
+       /*
+        * in case of non cached mode always drop the
+        * inode because we want the inode attribute
+        * to always match that on the server.
+        */
+       return 1;
+}
+
 static int v9fs_write_inode(struct inode *inode,
                            struct writeback_control *wbc)
 {
@@ -268,6 +283,7 @@ static const struct super_operations v9fs_super_ops = {
        .alloc_inode = v9fs_alloc_inode,
        .free_inode = v9fs_free_inode,
        .statfs = simple_statfs,
+       .drop_inode = v9fs_drop_inode,
        .evict_inode = v9fs_evict_inode,
        .show_options = v9fs_show_options,
        .umount_begin = v9fs_umount_begin,
@@ -278,6 +294,7 @@ static const struct super_operations v9fs_super_ops_dotl = {
        .alloc_inode = v9fs_alloc_inode,
        .free_inode = v9fs_free_inode,
        .statfs = v9fs_statfs,
+       .drop_inode = v9fs_drop_inode,
        .evict_inode = v9fs_evict_inode,
        .show_options = v9fs_show_options,
        .umount_begin = v9fs_umount_begin,
index 114328acde7202ed201fc8e776ed9cd73176d765..a200442010025a0d8ee7b421d12edb32ff5c5a01 100644 (file)
@@ -49,13 +49,15 @@ int bch2_backpointer_invalid(struct bch_fs *c, struct bkey_s_c k,
        if (!bch2_dev_exists2(c, bp.k->p.inode))
                return 0;
 
+       struct bch_dev *ca = bch_dev_bkey_exists(c, bp.k->p.inode);
        struct bpos bucket = bp_pos_to_bucket(c, bp.k->p);
        int ret = 0;
 
-       bkey_fsck_err_on(!bpos_eq(bp.k->p, bucket_pos_to_bp(c, bucket, bp.v->bucket_offset)),
+       bkey_fsck_err_on((bp.v->bucket_offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT) >= ca->mi.bucket_size ||
+                        !bpos_eq(bp.k->p, bucket_pos_to_bp(c, bucket, bp.v->bucket_offset)),
                         c, err,
-                        backpointer_pos_wrong,
-                        "backpointer at wrong pos");
+                        backpointer_bucket_offset_wrong,
+                        "backpointer bucket_offset wrong");
 fsck_err:
        return ret;
 }
@@ -468,7 +470,7 @@ found:
                goto err;
        }
 
-       bio = bio_alloc(ca->disk_sb.bdev, 1, REQ_OP_READ, GFP_KERNEL);
+       bio = bio_alloc(ca->disk_sb.bdev, buf_pages(data_buf, bytes), REQ_OP_READ, GFP_KERNEL);
        bio->bi_iter.bi_sector = p.ptr.offset;
        bch2_bio_map(bio, data_buf, bytes);
        ret = submit_bio_wait(bio);
index da012ca7daee5501fe04be48bc875c918abbb33a..85949b9fd880ce2fcce508ba4018350a5dfac9ca 100644 (file)
@@ -53,14 +53,11 @@ static inline struct bpos bucket_pos_to_bp(const struct bch_fs *c,
                                           u64 bucket_offset)
 {
        struct bch_dev *ca = bch_dev_bkey_exists(c, bucket.inode);
-       struct bpos ret;
-
-       ret = POS(bucket.inode,
-                 (bucket_to_sector(ca, bucket.offset) <<
-                  MAX_EXTENT_COMPRESS_RATIO_SHIFT) + bucket_offset);
+       struct bpos ret = POS(bucket.inode,
+                             (bucket_to_sector(ca, bucket.offset) <<
+                              MAX_EXTENT_COMPRESS_RATIO_SHIFT) + bucket_offset);
 
        EBUG_ON(!bkey_eq(bucket, bp_pos_to_bucket(c, ret)));
-
        return ret;
 }
 
index a31a5f706929eb2006e4867a38123b9526639cee..91c3c1fef233d118fb083dae3a60a5e779e3cdaf 100644 (file)
@@ -709,6 +709,8 @@ struct btree_trans_buf {
        x(stripe_delete)                                                \
        x(reflink)                                                      \
        x(fallocate)                                                    \
+       x(fsync)                                                        \
+       x(dio_write)                                                    \
        x(discard)                                                      \
        x(discard_fast)                                                 \
        x(invalidate)                                                   \
index 364ae42022af1750f9887d3f16c566a676b30776..f7fbfccd2b1e4d7e6bafabd839a6917de906edf9 100644 (file)
@@ -578,7 +578,8 @@ struct bch_member {
        __le64                  nbuckets;       /* device size */
        __le16                  first_bucket;   /* index of first bucket used */
        __le16                  bucket_size;    /* sectors */
-       __le32                  pad;
+       __u8                    btree_bitmap_shift;
+       __u8                    pad[3];
        __le64                  last_mount;     /* time_t */
 
        __le64                  flags;
@@ -587,6 +588,7 @@ struct bch_member {
        __le64                  errors_at_reset[BCH_MEMBER_ERROR_NR];
        __le64                  errors_reset_time;
        __le64                  seq;
+       __le64                  btree_allocated_bitmap;
 };
 
 #define BCH_MEMBER_V1_BYTES    56
@@ -876,7 +878,8 @@ struct bch_sb_field_downgrade {
        x(rebalance_work,               BCH_VERSION(1,  3))             \
        x(member_seq,                   BCH_VERSION(1,  4))             \
        x(subvolume_fs_parent,          BCH_VERSION(1,  5))             \
-       x(btree_subvolume_children,     BCH_VERSION(1,  6))
+       x(btree_subvolume_children,     BCH_VERSION(1,  6))             \
+       x(mi_btree_bitmap,              BCH_VERSION(1,  7))
 
 enum bcachefs_metadata_version {
        bcachefs_metadata_version_min = 9,
@@ -1314,7 +1317,7 @@ static inline __u64 __bset_magic(struct bch_sb *sb)
        x(write_buffer_keys,    11)             \
        x(datetime,             12)
 
-enum {
+enum bch_jset_entry_type {
 #define x(f, nr)       BCH_JSET_ENTRY_##f      = nr,
        BCH_JSET_ENTRY_TYPES()
 #undef x
@@ -1360,7 +1363,7 @@ struct jset_entry_blacklist_v2 {
        x(inodes,               1)              \
        x(key_version,          2)
 
-enum {
+enum bch_fs_usage_type {
 #define x(f, nr)       BCH_FS_USAGE_##f        = nr,
        BCH_FS_USAGE_TYPES()
 #undef x
@@ -1501,7 +1504,8 @@ enum btree_id_flags {
          BIT_ULL(KEY_TYPE_stripe))                                             \
        x(reflink,              7,      BTREE_ID_EXTENTS|BTREE_ID_DATA,         \
          BIT_ULL(KEY_TYPE_reflink_v)|                                          \
-         BIT_ULL(KEY_TYPE_indirect_inline_data))                               \
+         BIT_ULL(KEY_TYPE_indirect_inline_data)|                               \
+         BIT_ULL(KEY_TYPE_error))                                              \
        x(subvolumes,           8,      0,                                      \
          BIT_ULL(KEY_TYPE_subvolume))                                          \
        x(snapshots,            9,      0,                                      \
index cf23ff47bed8be588593a7fb193ee21ca8298c65..3a45d128f608db86d060d43573219d60762e3038 100644 (file)
@@ -314,6 +314,12 @@ static inline unsigned bkeyp_key_u64s(const struct bkey_format *format,
        return bkey_packed(k) ? format->key_u64s : BKEY_U64s;
 }
 
+static inline bool bkeyp_u64s_valid(const struct bkey_format *f,
+                                   const struct bkey_packed *k)
+{
+       return ((unsigned) k->u64s - bkeyp_key_u64s(f, k) <= U8_MAX - BKEY_U64s);
+}
+
 static inline unsigned bkeyp_key_bytes(const struct bkey_format *format,
                                       const struct bkey_packed *k)
 {
index 5e52684764eb14de4d8433abd5954a829648440b..db336a43fc083a79615e81ce9da37ff4877005f9 100644 (file)
@@ -171,11 +171,15 @@ int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
        if (type >= BKEY_TYPE_NR)
                return 0;
 
-       bkey_fsck_err_on((flags & BKEY_INVALID_COMMIT) &&
+       bkey_fsck_err_on((type == BKEY_TYPE_btree ||
+                         (flags & BKEY_INVALID_COMMIT)) &&
                         !(bch2_key_types_allowed[type] & BIT_ULL(k.k->type)), c, err,
                         bkey_invalid_type_for_btree,
                         "invalid key type for btree %s (%s)",
-                        bch2_btree_node_type_str(type), bch2_bkey_types[k.k->type]);
+                        bch2_btree_node_type_str(type),
+                        k.k->type < KEY_TYPE_MAX
+                        ? bch2_bkey_types[k.k->type]
+                        : "(unknown)");
 
        if (btree_node_type_is_extents(type) && !bkey_whiteout(k.k)) {
                bkey_fsck_err_on(k.k->size == 0, c, err,
index 84474324dba9b508141f0e886bafbd8a95d47537..02c70e813face0ce975f1f700e55a34743d286ea 100644 (file)
@@ -709,9 +709,31 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_trans *trans,
        struct bch_fs *c = trans->c;
        struct btree_cache *bc = &c->btree_cache;
        struct btree *b;
-       u32 seq;
 
-       BUG_ON(level + 1 >= BTREE_MAX_DEPTH);
+       if (unlikely(level >= BTREE_MAX_DEPTH)) {
+               int ret = bch2_fs_topology_error(c, "attempting to get btree node at level %u, >= max depth %u",
+                                                level, BTREE_MAX_DEPTH);
+               return ERR_PTR(ret);
+       }
+
+       if (unlikely(!bkey_is_btree_ptr(&k->k))) {
+               struct printbuf buf = PRINTBUF;
+               bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k));
+
+               int ret = bch2_fs_topology_error(c, "attempting to get btree node with non-btree key %s", buf.buf);
+               printbuf_exit(&buf);
+               return ERR_PTR(ret);
+       }
+
+       if (unlikely(k->k.u64s > BKEY_BTREE_PTR_U64s_MAX)) {
+               struct printbuf buf = PRINTBUF;
+               bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k));
+
+               int ret = bch2_fs_topology_error(c, "attempting to get btree node with too big key %s", buf.buf);
+               printbuf_exit(&buf);
+               return ERR_PTR(ret);
+       }
+
        /*
         * Parent node must be locked, else we could read in a btree node that's
         * been freed:
@@ -752,34 +774,26 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_trans *trans,
        }
 
        set_btree_node_read_in_flight(b);
-
        six_unlock_write(&b->c.lock);
-       seq = six_lock_seq(&b->c.lock);
-       six_unlock_intent(&b->c.lock);
 
-       /* Unlock before doing IO: */
-       if (path && sync)
-               bch2_trans_unlock_noassert(trans);
-
-       bch2_btree_node_read(trans, b, sync);
+       if (path) {
+               u32 seq = six_lock_seq(&b->c.lock);
 
-       if (!sync)
-               return NULL;
+               /* Unlock before doing IO: */
+               six_unlock_intent(&b->c.lock);
+               bch2_trans_unlock_noassert(trans);
 
-       if (path) {
-               int ret = bch2_trans_relock(trans) ?:
-                       bch2_btree_path_relock_intent(trans, path);
-               if (ret) {
-                       BUG_ON(!trans->restarted);
-                       return ERR_PTR(ret);
-               }
-       }
+               bch2_btree_node_read(trans, b, sync);
 
-       if (!six_relock_type(&b->c.lock, lock_type, seq)) {
-               BUG_ON(!path);
+               if (!sync)
+                       return NULL;
 
-               trace_and_count(c, trans_restart_relock_after_fill, trans, _THIS_IP_, path);
-               return ERR_PTR(btree_trans_restart(trans, BCH_ERR_transaction_restart_relock_after_fill));
+               if (!six_relock_type(&b->c.lock, lock_type, seq))
+                       b = NULL;
+       } else {
+               bch2_btree_node_read(trans, b, sync);
+               if (lock_type == SIX_LOCK_read)
+                       six_lock_downgrade(&b->c.lock);
        }
 
        return b;
@@ -1112,18 +1126,19 @@ int bch2_btree_node_prefetch(struct btree_trans *trans,
 {
        struct bch_fs *c = trans->c;
        struct btree_cache *bc = &c->btree_cache;
-       struct btree *b;
 
        BUG_ON(path && !btree_node_locked(path, level + 1));
        BUG_ON(level >= BTREE_MAX_DEPTH);
 
-       b = btree_cache_find(bc, k);
+       struct btree *b = btree_cache_find(bc, k);
        if (b)
                return 0;
 
        b = bch2_btree_node_fill(trans, path, k, btree_id,
                                 level, SIX_LOCK_read, false);
-       return PTR_ERR_OR_ZERO(b);
+       if (!IS_ERR_OR_NULL(b))
+               six_unlock_read(&b->c.lock);
+       return bch2_trans_relock(trans) ?: PTR_ERR_OR_ZERO(b);
 }
 
 void bch2_btree_node_evict(struct btree_trans *trans, const struct bkey_i *k)
@@ -1148,6 +1163,8 @@ wait_on_io:
 
        btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_intent);
        btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_write);
+       if (unlikely(b->hash_val != btree_ptr_hash_val(k)))
+               goto out;
 
        if (btree_node_dirty(b)) {
                __bch2_btree_node_write(c, b, BTREE_WRITE_cache_reclaim);
@@ -1162,7 +1179,7 @@ wait_on_io:
        btree_node_data_free(c, b);
        bch2_btree_node_hash_remove(bc, b);
        mutex_unlock(&bc->lock);
-
+out:
        six_unlock_write(&b->c.lock);
        six_unlock_intent(&b->c.lock);
 }
index d2555da55c6da3750af9fab2538e3653118a48d9..791470b0c654553e2fbb9216fb60df1eb8c5fec2 100644 (file)
@@ -828,6 +828,7 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
        struct bch_fs *c = trans->c;
        struct bkey deleted = KEY(0, 0, 0);
        struct bkey_s_c old = (struct bkey_s_c) { &deleted, NULL };
+       struct printbuf buf = PRINTBUF;
        int ret = 0;
 
        deleted.p = k->k->p;
@@ -848,11 +849,23 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
        if (ret)
                goto err;
 
+       if (mustfix_fsck_err_on(level && !bch2_dev_btree_bitmap_marked(c, *k),
+                               c, btree_bitmap_not_marked,
+                               "btree ptr not marked in member info btree allocated bitmap\n  %s",
+                               (bch2_bkey_val_to_text(&buf, c, *k),
+                                buf.buf))) {
+               mutex_lock(&c->sb_lock);
+               bch2_dev_btree_bitmap_mark(c, *k);
+               bch2_write_super(c);
+               mutex_unlock(&c->sb_lock);
+       }
+
        ret = commit_do(trans, NULL, NULL, 0,
                        bch2_key_trigger(trans, btree_id, level, old,
                                         unsafe_bkey_s_c_to_s(*k), BTREE_TRIGGER_GC));
 fsck_err:
 err:
+       printbuf_exit(&buf);
        bch_err_fn(c, ret);
        return ret;
 }
@@ -1574,7 +1587,7 @@ static int bch2_gc_write_reflink_key(struct btree_trans *trans,
                struct bkey_i *new = bch2_bkey_make_mut_noupdate(trans, k);
                ret = PTR_ERR_OR_ZERO(new);
                if (ret)
-                       return ret;
+                       goto out;
 
                if (!r->refcount)
                        new->k.type = KEY_TYPE_deleted;
@@ -1582,6 +1595,7 @@ static int bch2_gc_write_reflink_key(struct btree_trans *trans,
                        *bkey_refcount(bkey_i_to_s(new)) = cpu_to_le64(r->refcount);
                ret = bch2_trans_update(trans, iter, new, 0);
        }
+out:
 fsck_err:
        printbuf_exit(&buf);
        return ret;
index d7de82ac389354f9a0d5eef0a66c8694f1752b94..debb0edc3455afa661c0104e6e29fe232bcd18b8 100644 (file)
@@ -831,7 +831,7 @@ static int bset_key_invalid(struct bch_fs *c, struct btree *b,
                (rw == WRITE ? bch2_bkey_val_invalid(c, k, READ, err) : 0);
 }
 
-static bool __bkey_valid(struct bch_fs *c, struct btree *b,
+static bool bkey_packed_valid(struct bch_fs *c, struct btree *b,
                         struct bset *i, struct bkey_packed *k)
 {
        if (bkey_p_next(k) > vstruct_last(i))
@@ -840,7 +840,7 @@ static bool __bkey_valid(struct bch_fs *c, struct btree *b,
        if (k->format > KEY_FORMAT_CURRENT)
                return false;
 
-       if (k->u64s < bkeyp_key_u64s(&b->format, k))
+       if (!bkeyp_u64s_valid(&b->format, k))
                return false;
 
        struct printbuf buf = PRINTBUF;
@@ -884,11 +884,13 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b,
                                 "invalid bkey format %u", k->format))
                        goto drop_this_key;
 
-               if (btree_err_on(k->u64s < bkeyp_key_u64s(&b->format, k),
+               if (btree_err_on(!bkeyp_u64s_valid(&b->format, k),
                                 -BCH_ERR_btree_node_read_err_fixable,
                                 c, NULL, b, i,
                                 btree_node_bkey_bad_u64s,
-                                "k->u64s too small (%u < %u)", k->u64s, bkeyp_key_u64s(&b->format, k)))
+                                "bad k->u64s %u (min %u max %zu)", k->u64s,
+                                bkeyp_key_u64s(&b->format, k),
+                                U8_MAX - BKEY_U64s + bkeyp_key_u64s(&b->format, k)))
                        goto drop_this_key;
 
                if (!write)
@@ -947,13 +949,12 @@ drop_this_key:
                         * do
                         */
 
-                       if (!__bkey_valid(c, b, i, (void *) ((u64 *) k + next_good_key))) {
+                       if (!bkey_packed_valid(c, b, i, (void *) ((u64 *) k + next_good_key))) {
                                for (next_good_key = 1;
                                     next_good_key < (u64 *) vstruct_last(i) - (u64 *) k;
                                     next_good_key++)
-                                       if (__bkey_valid(c, b, i, (void *) ((u64 *) k + next_good_key)))
+                                       if (bkey_packed_valid(c, b, i, (void *) ((u64 *) k + next_good_key)))
                                                goto got_good_key;
-
                        }
 
                        /*
@@ -1339,7 +1340,9 @@ start:
                               rb->start_time);
        bio_put(&rb->bio);
 
-       if (saw_error && !btree_node_read_error(b)) {
+       if (saw_error &&
+           !btree_node_read_error(b) &&
+           c->curr_recovery_pass != BCH_RECOVERY_PASS_scan_for_btree_nodes) {
                printbuf_reset(&buf);
                bch2_bpos_to_text(&buf, b->key.k.p);
                bch_err_ratelimited(c, "%s: rewriting btree node at btree=%s level=%u %s due to error",
index 1d58d447b386cdf74ecce2609f8aa23851ae4057..1c70836dd7cce4988ef8cf166ee0797fd8f8269e 100644 (file)
@@ -498,8 +498,13 @@ static inline void set_btree_iter_dontneed(struct btree_iter *iter)
 {
        struct btree_trans *trans = iter->trans;
 
-       if (!trans->restarted)
-               btree_iter_path(trans, iter)->preserve = false;
+       if (!iter->path || trans->restarted)
+               return;
+
+       struct btree_path *path = btree_iter_path(trans, iter);
+       path->preserve          = false;
+       if (path->ref == 1)
+               path->should_be_locked  = false;
 }
 
 void *__bch2_trans_kmalloc(struct btree_trans *, size_t);
index 88a3582a32757e34a28eb37143f9ff78a88a4085..e8c1c530cd95f5bb1c34cb39f848cd842b0a88c6 100644 (file)
@@ -842,8 +842,6 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink,
         * Newest freed entries are at the end of the list - once we hit one
         * that's too new to be freed, we can bail out:
         */
-       scanned += bc->nr_freed_nonpcpu;
-
        list_for_each_entry_safe(ck, t, &bc->freed_nonpcpu, list) {
                if (!poll_state_synchronize_srcu(&c->btree_trans_barrier,
                                                 ck->btree_trans_barrier_seq))
@@ -857,11 +855,6 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink,
                bc->nr_freed_nonpcpu--;
        }
 
-       if (scanned >= nr)
-               goto out;
-
-       scanned += bc->nr_freed_pcpu;
-
        list_for_each_entry_safe(ck, t, &bc->freed_pcpu, list) {
                if (!poll_state_synchronize_srcu(&c->btree_trans_barrier,
                                                 ck->btree_trans_barrier_seq))
@@ -875,9 +868,6 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink,
                bc->nr_freed_pcpu--;
        }
 
-       if (scanned >= nr)
-               goto out;
-
        rcu_read_lock();
        tbl = rht_dereference_rcu(bc->table.tbl, &bc->table);
        if (bc->shrink_iter >= tbl->size)
@@ -893,12 +883,12 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink,
                        next = rht_dereference_bucket_rcu(pos->next, tbl, bc->shrink_iter);
                        ck = container_of(pos, struct bkey_cached, hash);
 
-                       if (test_bit(BKEY_CACHED_DIRTY, &ck->flags))
+                       if (test_bit(BKEY_CACHED_DIRTY, &ck->flags)) {
                                goto next;
-
-                       if (test_bit(BKEY_CACHED_ACCESSED, &ck->flags))
+                       } else if (test_bit(BKEY_CACHED_ACCESSED, &ck->flags)) {
                                clear_bit(BKEY_CACHED_ACCESSED, &ck->flags);
-                       else if (bkey_cached_lock_for_evict(ck)) {
+                               goto next;
+                       } else if (bkey_cached_lock_for_evict(ck)) {
                                bkey_cached_evict(bc, ck);
                                bkey_cached_free(bc, ck);
                        }
@@ -916,7 +906,6 @@ next:
        } while (scanned < nr && bc->shrink_iter != start);
 
        rcu_read_unlock();
-out:
        memalloc_nofs_restore(flags);
        srcu_read_unlock(&c->btree_trans_barrier, srcu_idx);
        mutex_unlock(&bc->lock);
index 556f76f5c84e1613c332e7443e6bb8b1602dd359..45cb8149d374c2878e8c607282ca4e5e7875f063 100644 (file)
@@ -57,13 +57,14 @@ static void found_btree_node_to_key(struct bkey_i *k, const struct found_btree_n
        bp->v.seq               = cpu_to_le64(f->cookie);
        bp->v.sectors_written   = 0;
        bp->v.flags             = 0;
+       bp->v.sectors_written   = cpu_to_le16(f->sectors_written);
        bp->v.min_key           = f->min_key;
        SET_BTREE_PTR_RANGE_UPDATED(&bp->v, f->range_updated);
        memcpy(bp->v.start, f->ptrs, sizeof(struct bch_extent_ptr) * f->nr_ptrs);
 }
 
 static bool found_btree_node_is_readable(struct btree_trans *trans,
-                                        const struct found_btree_node *f)
+                                        struct found_btree_node *f)
 {
        struct { __BKEY_PADDED(k, BKEY_BTREE_PTR_VAL_U64s_MAX); } k;
 
@@ -71,8 +72,10 @@ static bool found_btree_node_is_readable(struct btree_trans *trans,
 
        struct btree *b = bch2_btree_node_get_noiter(trans, &k.k, f->btree_id, f->level, false);
        bool ret = !IS_ERR_OR_NULL(b);
-       if (ret)
+       if (ret) {
+               f->sectors_written = b->written;
                six_unlock_read(&b->c.lock);
+       }
 
        /*
         * We might update this node's range; if that happens, we need the node
@@ -133,9 +136,19 @@ static void try_read_btree_node(struct find_btree_nodes *f, struct bch_dev *ca,
        if (le64_to_cpu(bn->magic) != bset_magic(c))
                return;
 
+       if (bch2_csum_type_is_encryption(BSET_CSUM_TYPE(&bn->keys))) {
+               struct nonce nonce = btree_nonce(&bn->keys, 0);
+               unsigned bytes = (void *) &bn->keys - (void *) &bn->flags;
+
+               bch2_encrypt(c, BSET_CSUM_TYPE(&bn->keys), nonce, &bn->flags, bytes);
+       }
+
        if (btree_id_is_alloc(BTREE_NODE_ID(bn)))
                return;
 
+       if (BTREE_NODE_LEVEL(bn) >= BTREE_MAX_DEPTH)
+               return;
+
        rcu_read_lock();
        struct found_btree_node n = {
                .btree_id       = BTREE_NODE_ID(bn),
@@ -195,8 +208,13 @@ static int read_btree_nodes_worker(void *p)
                                last_print = jiffies;
                        }
 
-                       try_read_btree_node(w->f, ca, bio, buf,
-                                           bucket * ca->mi.bucket_size + bucket_offset);
+                       u64 sector = bucket * ca->mi.bucket_size + bucket_offset;
+
+                       if (c->sb.version_upgrade_complete >= bcachefs_metadata_version_mi_btree_bitmap &&
+                           !bch2_dev_btree_bitmap_marked_sectors(ca, sector, btree_sectors(c)))
+                               continue;
+
+                       try_read_btree_node(w->f, ca, bio, buf, sector);
                }
 err:
        bio_put(bio);
@@ -287,6 +305,8 @@ again:
 
                        start->max_key = bpos_predecessor(n->min_key);
                        start->range_updated = true;
+               } else if (n->level) {
+                       n->overwritten = true;
                } else {
                        struct printbuf buf = PRINTBUF;
 
index abb7b27d556a9ff0f09e797494437a513122d8d3..5cfaeb5ac831b6396399d71858d2934e7d63c544 100644 (file)
@@ -9,6 +9,7 @@ struct found_btree_node {
        bool                    overwritten:1;
        u8                      btree_id;
        u8                      level;
+       unsigned                sectors_written;
        u32                     seq;
        u64                     cookie;
 
index aa9da49707404015a558c9c6e9339b733d0c98c3..bbec91e8e6506fa32611b340dc1a3a4a104aeed6 100644 (file)
@@ -397,12 +397,13 @@ static int btree_key_can_insert_cached(struct btree_trans *trans, unsigned flags
        struct bkey_cached *ck = (void *) path->l[0].b;
        unsigned new_u64s;
        struct bkey_i *new_k;
+       unsigned watermark = flags & BCH_WATERMARK_MASK;
 
        EBUG_ON(path->level);
 
-       if (!test_bit(BKEY_CACHED_DIRTY, &ck->flags) &&
-           bch2_btree_key_cache_must_wait(c) &&
-           !(flags & BCH_TRANS_COMMIT_journal_reclaim))
+       if (watermark < BCH_WATERMARK_reclaim &&
+           !test_bit(BKEY_CACHED_DIRTY, &ck->flags) &&
+           bch2_btree_key_cache_must_wait(c))
                return -BCH_ERR_btree_insert_need_journal_reclaim;
 
        /*
@@ -499,9 +500,8 @@ static int run_one_trans_trigger(struct btree_trans *trans, struct btree_insert_
 }
 
 static int run_btree_triggers(struct btree_trans *trans, enum btree_id btree_id,
-                             struct btree_insert_entry *btree_id_start)
+                             unsigned btree_id_start)
 {
-       struct btree_insert_entry *i;
        bool trans_trigger_run;
        int ret, overwrite;
 
@@ -514,13 +514,13 @@ static int run_btree_triggers(struct btree_trans *trans, enum btree_id btree_id,
                do {
                        trans_trigger_run = false;
 
-                       for (i = btree_id_start;
-                            i < trans->updates + trans->nr_updates && i->btree_id <= btree_id;
+                       for (unsigned i = btree_id_start;
+                            i < trans->nr_updates && trans->updates[i].btree_id <= btree_id;
                             i++) {
-                               if (i->btree_id != btree_id)
+                               if (trans->updates[i].btree_id != btree_id)
                                        continue;
 
-                               ret = run_one_trans_trigger(trans, i, overwrite);
+                               ret = run_one_trans_trigger(trans, trans->updates + i, overwrite);
                                if (ret < 0)
                                        return ret;
                                if (ret)
@@ -534,8 +534,7 @@ static int run_btree_triggers(struct btree_trans *trans, enum btree_id btree_id,
 
 static int bch2_trans_commit_run_triggers(struct btree_trans *trans)
 {
-       struct btree_insert_entry *btree_id_start = trans->updates;
-       unsigned btree_id = 0;
+       unsigned btree_id = 0, btree_id_start = 0;
        int ret = 0;
 
        /*
@@ -549,8 +548,8 @@ static int bch2_trans_commit_run_triggers(struct btree_trans *trans)
                if (btree_id == BTREE_ID_alloc)
                        continue;
 
-               while (btree_id_start < trans->updates + trans->nr_updates &&
-                      btree_id_start->btree_id < btree_id)
+               while (btree_id_start < trans->nr_updates &&
+                      trans->updates[btree_id_start].btree_id < btree_id)
                        btree_id_start++;
 
                ret = run_btree_triggers(trans, btree_id, btree_id_start);
@@ -558,11 +557,13 @@ static int bch2_trans_commit_run_triggers(struct btree_trans *trans)
                        return ret;
        }
 
-       trans_for_each_update(trans, i) {
+       for (unsigned idx = 0; idx < trans->nr_updates; idx++) {
+               struct btree_insert_entry *i = trans->updates + idx;
+
                if (i->btree_id > BTREE_ID_alloc)
                        break;
                if (i->btree_id == BTREE_ID_alloc) {
-                       ret = run_btree_triggers(trans, BTREE_ID_alloc, i);
+                       ret = run_btree_triggers(trans, BTREE_ID_alloc, idx);
                        if (ret)
                                return ret;
                        break;
@@ -826,7 +827,8 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans, unsigned flags
        struct bch_fs *c = trans->c;
        int ret = 0, u64s_delta = 0;
 
-       trans_for_each_update(trans, i) {
+       for (unsigned idx = 0; idx < trans->nr_updates; idx++) {
+               struct btree_insert_entry *i = trans->updates + idx;
                if (i->cached)
                        continue;
 
index e0c982a4195c764ab8a415b5f7f80cbff88c1935..c69b233c41bb3d07a02ca296c03429360ff2294e 100644 (file)
@@ -321,9 +321,9 @@ struct bkey_cached {
        struct btree_bkey_cached_common c;
 
        unsigned long           flags;
+       unsigned long           btree_trans_barrier_seq;
        u16                     u64s;
        bool                    valid;
-       u32                     btree_trans_barrier_seq;
        struct bkey_cached_key  key;
 
        struct rhash_head       hash;
index c4a5e83a56a436548263445e3b7a329644757cc7..b4efd8cc4d1a2bfc62a9742d6f4df3e9a0f0aac5 100644 (file)
@@ -21,6 +21,7 @@
 #include "keylist.h"
 #include "recovery_passes.h"
 #include "replicas.h"
+#include "sb-members.h"
 #include "super-io.h"
 #include "trace.h"
 
@@ -605,6 +606,26 @@ static void btree_update_add_key(struct btree_update *as,
        bch2_keylist_push(keys);
 }
 
+static bool btree_update_new_nodes_marked_sb(struct btree_update *as)
+{
+       for_each_keylist_key(&as->new_keys, k)
+               if (!bch2_dev_btree_bitmap_marked(as->c, bkey_i_to_s_c(k)))
+                       return false;
+       return true;
+}
+
+static void btree_update_new_nodes_mark_sb(struct btree_update *as)
+{
+       struct bch_fs *c = as->c;
+
+       mutex_lock(&c->sb_lock);
+       for_each_keylist_key(&as->new_keys, k)
+               bch2_dev_btree_bitmap_mark(c, bkey_i_to_s_c(k));
+
+       bch2_write_super(c);
+       mutex_unlock(&c->sb_lock);
+}
+
 /*
  * The transactional part of an interior btree node update, where we journal the
  * update we did to the interior node and update alloc info:
@@ -662,6 +683,9 @@ static void btree_update_nodes_written(struct btree_update *as)
        if (ret)
                goto err;
 
+       if (!btree_update_new_nodes_marked_sb(as))
+               btree_update_new_nodes_mark_sb(as);
+
        /*
         * Wait for any in flight writes to finish before we free the old nodes
         * on disk:
@@ -1280,23 +1304,29 @@ static void bch2_btree_set_root_inmem(struct bch_fs *c, struct btree *b)
        bch2_recalc_btree_reserve(c);
 }
 
-static void bch2_btree_set_root(struct btree_update *as,
-                               struct btree_trans *trans,
-                               struct btree_path *path,
-                               struct btree *b)
+static int bch2_btree_set_root(struct btree_update *as,
+                              struct btree_trans *trans,
+                              struct btree_path *path,
+                              struct btree *b,
+                              bool nofail)
 {
        struct bch_fs *c = as->c;
-       struct btree *old;
 
        trace_and_count(c, btree_node_set_root, trans, b);
 
-       old = btree_node_root(c, b);
+       struct btree *old = btree_node_root(c, b);
 
        /*
         * Ensure no one is using the old root while we switch to the
         * new root:
         */
-       bch2_btree_node_lock_write_nofail(trans, path, &old->c);
+       if (nofail) {
+               bch2_btree_node_lock_write_nofail(trans, path, &old->c);
+       } else {
+               int ret = bch2_btree_node_lock_write(trans, path, &old->c);
+               if (ret)
+                       return ret;
+       }
 
        bch2_btree_set_root_inmem(c, b);
 
@@ -1310,6 +1340,7 @@ static void bch2_btree_set_root(struct btree_update *as,
         * depend on the new root would have to update the new root.
         */
        bch2_btree_node_unlock_write(trans, path, old);
+       return 0;
 }
 
 /* Interior node updates: */
@@ -1652,15 +1683,16 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans,
        if (parent) {
                /* Split a non root node */
                ret = bch2_btree_insert_node(as, trans, path, parent, &as->parent_keys);
-               if (ret)
-                       goto err;
        } else if (n3) {
-               bch2_btree_set_root(as, trans, trans->paths + path, n3);
+               ret = bch2_btree_set_root(as, trans, trans->paths + path, n3, false);
        } else {
                /* Root filled up but didn't need to be split */
-               bch2_btree_set_root(as, trans, trans->paths + path, n1);
+               ret = bch2_btree_set_root(as, trans, trans->paths + path, n1, false);
        }
 
+       if (ret)
+               goto err;
+
        if (n3) {
                bch2_btree_update_get_open_buckets(as, n3);
                bch2_btree_node_write(c, n3, SIX_LOCK_intent, 0);
@@ -1863,7 +1895,9 @@ static void __btree_increase_depth(struct btree_update *as, struct btree_trans *
        bch2_keylist_add(&as->parent_keys, &b->key);
        btree_split_insert_keys(as, trans, path_idx, n, &as->parent_keys);
 
-       bch2_btree_set_root(as, trans, path, n);
+       int ret = bch2_btree_set_root(as, trans, path, n, true);
+       BUG_ON(ret);
+
        bch2_btree_update_get_open_buckets(as, n);
        bch2_btree_node_write(c, n, SIX_LOCK_intent, 0);
        bch2_trans_node_add(trans, path, n);
@@ -1916,6 +1950,22 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans,
        BUG_ON(!trans->paths[path].should_be_locked);
        BUG_ON(!btree_node_locked(&trans->paths[path], level));
 
+       /*
+        * Work around a deadlock caused by the btree write buffer not doing
+        * merges and leaving tons of merges for us to do - we really don't need
+        * to be doing merges at all from the interior update path, and if the
+        * interior update path is generating too many new interior updates we
+        * deadlock:
+        */
+       if ((flags & BCH_WATERMARK_MASK) == BCH_WATERMARK_interior_updates)
+               return 0;
+
+       if ((flags & BCH_WATERMARK_MASK) <= BCH_WATERMARK_reclaim) {
+               flags &= ~BCH_WATERMARK_MASK;
+               flags |= BCH_WATERMARK_btree;
+               flags |= BCH_TRANS_COMMIT_journal_reclaim;
+       }
+
        b = trans->paths[path].l[level].b;
 
        if ((sib == btree_prev_sib && bpos_eq(b->data->min_key, POS_MIN)) ||
@@ -2061,6 +2111,10 @@ err:
                bch2_path_put(trans, new_path, true);
        bch2_path_put(trans, sib_path, true);
        bch2_trans_verify_locks(trans);
+       if (ret == -BCH_ERR_journal_reclaim_would_deadlock)
+               ret = 0;
+       if (!ret)
+               ret = bch2_trans_relock(trans);
        return ret;
 err_free_update:
        bch2_btree_node_free_never_used(as, trans, n);
@@ -2106,12 +2160,13 @@ int bch2_btree_node_rewrite(struct btree_trans *trans,
        if (parent) {
                bch2_keylist_add(&as->parent_keys, &n->key);
                ret = bch2_btree_insert_node(as, trans, iter->path, parent, &as->parent_keys);
-               if (ret)
-                       goto err;
        } else {
-               bch2_btree_set_root(as, trans, btree_iter_path(trans, iter), n);
+               ret = bch2_btree_set_root(as, trans, btree_iter_path(trans, iter), n, false);
        }
 
+       if (ret)
+               goto err;
+
        bch2_btree_update_get_open_buckets(as, n);
        bch2_btree_node_write(c, n, SIX_LOCK_intent, 0);
 
index baf63e2fddb64cd8f4c745d0cc80c864c86ffaa6..36a6f42aba5e6fc5a36418c1d7565e07e8f90420 100644 (file)
@@ -316,6 +316,16 @@ static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans)
                            bpos_gt(k->k.k.p, path->l[0].b->key.k.p)) {
                                bch2_btree_node_unlock_write(trans, path, path->l[0].b);
                                write_locked = false;
+
+                               ret = lockrestart_do(trans,
+                                       bch2_btree_iter_traverse(&iter) ?:
+                                       bch2_foreground_maybe_merge(trans, iter.path, 0,
+                                                       BCH_WATERMARK_reclaim|
+                                                       BCH_TRANS_COMMIT_journal_reclaim|
+                                                       BCH_TRANS_COMMIT_no_check_rw|
+                                                       BCH_TRANS_COMMIT_no_enospc));
+                               if (ret)
+                                       goto err;
                        }
                }
 
@@ -382,10 +392,10 @@ static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans)
 
                        ret = commit_do(trans, NULL, NULL,
                                        BCH_WATERMARK_reclaim|
+                                       BCH_TRANS_COMMIT_journal_reclaim|
                                        BCH_TRANS_COMMIT_no_check_rw|
                                        BCH_TRANS_COMMIT_no_enospc|
-                                       BCH_TRANS_COMMIT_no_journal_res|
-                                       BCH_TRANS_COMMIT_journal_reclaim,
+                                       BCH_TRANS_COMMIT_no_journal_res ,
                                        btree_write_buffered_insert(trans, i));
                        if (ret)
                                goto err;
index 941401a210f56993359548e51b5095d0db45e691..82f179258867b7b1b6e5f21905f0bc3d3eaee41c 100644 (file)
@@ -525,7 +525,6 @@ int bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
                        "different types of data in same bucket: %s, %s",
                        bch2_data_type_str(g->data_type),
                        bch2_data_type_str(data_type))) {
-               BUG();
                ret = -EIO;
                goto err;
        }
@@ -629,7 +628,6 @@ int bch2_check_bucket_ref(struct btree_trans *trans,
                        bch2_data_type_str(ptr_data_type),
                        (printbuf_reset(&buf),
                         bch2_bkey_val_to_text(&buf, c, k), buf.buf));
-               BUG();
                ret = -EIO;
                goto err;
        }
index 00aaf4bb513974a6b9c0353ea9445f92671c32eb..f9af5adabe83638eea7ffd15ea2f730085f81cc1 100644 (file)
@@ -395,14 +395,6 @@ static inline const char *bch2_data_type_str(enum bch_data_type type)
                : "(invalid data type)";
 }
 
-static inline void bch2_prt_data_type(struct printbuf *out, enum bch_data_type type)
-{
-       if (type < BCH_DATA_NR)
-               prt_str(out, __bch2_data_types[type]);
-       else
-               prt_printf(out, "(invalid data type %u)", type);
-}
-
 /* disk reservations: */
 
 static inline void bch2_disk_reservation_put(struct bch_fs *c,
index 72781aad6ba70ccc774b688c6a9d50b2dc21f133..4d14f19f51850e9d024ee69bd1f68d5a3743a2b0 100644 (file)
@@ -232,13 +232,15 @@ static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_a
        /* We need request_key() to be called before we punt to kthread: */
        opt_set(thr->opts, nostart, true);
 
+       bch2_thread_with_stdio_init(&thr->thr, &bch2_offline_fsck_ops);
+
        thr->c = bch2_fs_open(devs.data, arg.nr_devs, thr->opts);
 
        if (!IS_ERR(thr->c) &&
            thr->c->opts.errors == BCH_ON_ERROR_panic)
                thr->c->opts.errors = BCH_ON_ERROR_ro;
 
-       ret = bch2_run_thread_with_stdio(&thr->thr, &bch2_offline_fsck_ops);
+       ret = __bch2_run_thread_with_stdio(&thr->thr);
 out:
        darray_for_each(devs, i)
                kfree(*i);
index 4701457f6381ca820e17a12707009c272ed5b4ac..7ed779b411f61e4e3f05a703ce9e091474237939 100644 (file)
@@ -429,15 +429,20 @@ int bch2_rechecksum_bio(struct bch_fs *c, struct bio *bio,
                                extent_nonce(version, crc_old), bio);
 
        if (bch2_crc_cmp(merged, crc_old.csum) && !c->opts.no_data_io) {
-               bch_err(c, "checksum error in %s() (memory corruption or bug?)\n"
-                       "expected %0llx:%0llx got %0llx:%0llx (old type %s new type %s)",
-                       __func__,
-                       crc_old.csum.hi,
-                       crc_old.csum.lo,
-                       merged.hi,
-                       merged.lo,
-                       bch2_csum_types[crc_old.csum_type],
-                       bch2_csum_types[new_csum_type]);
+               struct printbuf buf = PRINTBUF;
+               prt_printf(&buf, "checksum error in %s() (memory corruption or bug?)\n"
+                          "expected %0llx:%0llx got %0llx:%0llx (old type ",
+                          __func__,
+                          crc_old.csum.hi,
+                          crc_old.csum.lo,
+                          merged.hi,
+                          merged.lo);
+               bch2_prt_csum_type(&buf, crc_old.csum_type);
+               prt_str(&buf, " new type ");
+               bch2_prt_csum_type(&buf, new_csum_type);
+               prt_str(&buf, ")");
+               bch_err(c, "%s", buf.buf);
+               printbuf_exit(&buf);
                return -EIO;
        }
 
index 1b8c2c1016dc6347ce12ef3161d4723835dfa56e..e40499fde9a4019fc75d62f825e9e5583caf803b 100644 (file)
@@ -61,11 +61,12 @@ static inline void bch2_csum_err_msg(struct printbuf *out,
                                     struct bch_csum expected,
                                     struct bch_csum got)
 {
-       prt_printf(out, "checksum error: got ");
+       prt_str(out, "checksum error, type ");
+       bch2_prt_csum_type(out, type);
+       prt_str(out, ": got ");
        bch2_csum_to_text(out, type, got);
        prt_str(out, " should be ");
        bch2_csum_to_text(out, type, expected);
-       prt_printf(out, " type %s", bch2_csum_types[type]);
 }
 
 int bch2_chacha_encrypt_key(struct bch_key *, struct nonce, void *, size_t);
index 58c2eb45570ff022764720f9beb10ecfa2926367..607fd5e232c902dbb39f3dac84ea2e214e6b106c 100644 (file)
@@ -47,14 +47,6 @@ static inline enum bch_compression_type bch2_compression_opt_to_type(unsigned v)
        return __bch2_compression_opt_to_type[bch2_compression_decode(v).type];
 }
 
-static inline void bch2_prt_compression_type(struct printbuf *out, enum bch_compression_type type)
-{
-       if (type < BCH_COMPRESSION_TYPE_NR)
-               prt_str(out, __bch2_compression_types[type]);
-       else
-               prt_printf(out, "(invalid compression type %u)", type);
-}
-
 int bch2_bio_uncompress_inplace(struct bch_fs *, struct bio *,
                                struct bch_extent_crc_unpacked *);
 int bch2_bio_uncompress(struct bch_fs *, struct bio *, struct bio *,
index 082075244e16aedc824249b239ecec6efb1a07fa..556a217108d32ef35890da0463751afc688186f3 100644 (file)
@@ -131,29 +131,33 @@ fsck_err:
 void bch2_stripe_to_text(struct printbuf *out, struct bch_fs *c,
                         struct bkey_s_c k)
 {
-       const struct bch_stripe *s = bkey_s_c_to_stripe(k).v;
-       unsigned i, nr_data = s->nr_blocks - s->nr_redundant;
+       const struct bch_stripe *sp = bkey_s_c_to_stripe(k).v;
+       struct bch_stripe s = {};
+
+       memcpy(&s, sp, min(sizeof(s), bkey_val_bytes(k.k)));
+
+       unsigned nr_data = s.nr_blocks - s.nr_redundant;
+
+       prt_printf(out, "algo %u sectors %u blocks %u:%u csum ",
+                  s.algorithm,
+                  le16_to_cpu(s.sectors),
+                  nr_data,
+                  s.nr_redundant);
+       bch2_prt_csum_type(out, s.csum_type);
+       prt_printf(out, " gran %u", 1U << s.csum_granularity_bits);
+
+       for (unsigned i = 0; i < s.nr_blocks; i++) {
+               const struct bch_extent_ptr *ptr = sp->ptrs + i;
+
+               if ((void *) ptr >= bkey_val_end(k))
+                       break;
+
+               bch2_extent_ptr_to_text(out, c, ptr);
 
-       prt_printf(out, "algo %u sectors %u blocks %u:%u csum %u gran %u",
-              s->algorithm,
-              le16_to_cpu(s->sectors),
-              nr_data,
-              s->nr_redundant,
-              s->csum_type,
-              1U << s->csum_granularity_bits);
-
-       for (i = 0; i < s->nr_blocks; i++) {
-               const struct bch_extent_ptr *ptr = s->ptrs + i;
-               struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
-               u32 offset;
-               u64 b = sector_to_bucket_and_offset(ca, ptr->offset, &offset);
-
-               prt_printf(out, " %u:%llu:%u", ptr->dev, b, offset);
-               if (i < nr_data)
-                       prt_printf(out, "#%u", stripe_blockcount_get(s, i));
-               prt_printf(out, " gen %u", ptr->gen);
-               if (ptr_stale(ca, ptr))
-                       prt_printf(out, " stale");
+               if (s.csum_type < BCH_CSUM_NR &&
+                   i < nr_data &&
+                   stripe_blockcount_offset(&s, i) < bkey_val_bytes(k.k))
+                       prt_printf(out,  "#%u", stripe_blockcount_get(sp, i));
        }
 }
 
@@ -607,10 +611,8 @@ static void ec_validate_checksums(struct bch_fs *c, struct ec_stripe_buf *buf)
                                struct printbuf err = PRINTBUF;
                                struct bch_dev *ca = bch_dev_bkey_exists(c, v->ptrs[i].dev);
 
-                               prt_printf(&err, "stripe checksum error: expected %0llx:%0llx got %0llx:%0llx (type %s)\n",
-                                          want.hi, want.lo,
-                                          got.hi, got.lo,
-                                          bch2_csum_types[v->csum_type]);
+                               prt_str(&err, "stripe ");
+                               bch2_csum_err_msg(&err, v->csum_type, want, got);
                                prt_printf(&err, "  for %ps at %u of\n  ", (void *) _RET_IP_, i);
                                bch2_bkey_val_to_text(&err, c, bkey_i_to_s_c(&buf->key));
                                bch_err_ratelimited(ca, "%s", err.buf);
index f4369b02e805f0a24572a8cf87d18867c3d3301a..f042616888b0a1d47d7797e987c912c58d0945b3 100644 (file)
@@ -32,6 +32,8 @@ static inline unsigned stripe_csums_per_device(const struct bch_stripe *s)
 static inline unsigned stripe_csum_offset(const struct bch_stripe *s,
                                          unsigned dev, unsigned csum_idx)
 {
+       EBUG_ON(s->csum_type >= BCH_CSUM_NR);
+
        unsigned csum_bytes = bch_crc_bytes[s->csum_type];
 
        return sizeof(struct bch_stripe) +
index 0e3ca99fbd2de1522c5e8dea8ac313232f60f7f3..1a331e539204852d4db9e7620df0282abe262f1e 100644 (file)
@@ -998,7 +998,9 @@ void bch2_extent_ptr_to_text(struct printbuf *out, struct bch_fs *c, const struc
                        prt_str(out, " cached");
                if (ptr->unwritten)
                        prt_str(out, " unwritten");
-               if (ca && ptr_stale(ca, ptr))
+               if (b >= ca->mi.first_bucket &&
+                   b <  ca->mi.nbuckets &&
+                   ptr_stale(ca, ptr))
                        prt_printf(out, " stale");
        }
 }
@@ -1028,11 +1030,12 @@ void bch2_bkey_ptrs_to_text(struct printbuf *out, struct bch_fs *c,
                        struct bch_extent_crc_unpacked crc =
                                bch2_extent_crc_unpack(k.k, entry_to_crc(entry));
 
-                       prt_printf(out, "crc: c_size %u size %u offset %u nonce %u csum %s compress ",
+                       prt_printf(out, "crc: c_size %u size %u offset %u nonce %u csum ",
                               crc.compressed_size,
                               crc.uncompressed_size,
-                              crc.offset, crc.nonce,
-                              bch2_csum_types[crc.csum_type]);
+                              crc.offset, crc.nonce);
+                       bch2_prt_csum_type(out, crc.csum_type);
+                       prt_str(out, " compress ");
                        bch2_prt_compression_type(out, crc.compression_type);
                        break;
                }
index f49e6c0f0f6835968202ab2f1fa194933945554a..b889370a5088113a2417787bdbb4b98a16597063 100644 (file)
@@ -387,6 +387,8 @@ static __always_inline long bch2_dio_write_done(struct dio_write *dio)
        ret = dio->op.error ?: ((long) dio->written << 9);
        bio_put(&dio->op.wbio.bio);
 
+       bch2_write_ref_put(dio->op.c, BCH_WRITE_REF_dio_write);
+
        /* inode->i_dio_count is our ref on inode and thus bch_fs */
        inode_dio_end(&inode->v);
 
@@ -590,22 +592,25 @@ ssize_t bch2_direct_write(struct kiocb *req, struct iov_iter *iter)
        prefetch(&inode->ei_inode);
        prefetch((void *) &inode->ei_inode + 64);
 
+       if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_dio_write))
+               return -EROFS;
+
        inode_lock(&inode->v);
 
        ret = generic_write_checks(req, iter);
        if (unlikely(ret <= 0))
-               goto err;
+               goto err_put_write_ref;
 
        ret = file_remove_privs(file);
        if (unlikely(ret))
-               goto err;
+               goto err_put_write_ref;
 
        ret = file_update_time(file);
        if (unlikely(ret))
-               goto err;
+               goto err_put_write_ref;
 
        if (unlikely((req->ki_pos|iter->count) & (block_bytes(c) - 1)))
-               goto err;
+               goto err_put_write_ref;
 
        inode_dio_begin(&inode->v);
        bch2_pagecache_block_get(inode);
@@ -645,7 +650,7 @@ ssize_t bch2_direct_write(struct kiocb *req, struct iov_iter *iter)
        }
 
        ret = bch2_dio_write_loop(dio);
-err:
+out:
        if (locked)
                inode_unlock(&inode->v);
        return ret;
@@ -653,7 +658,9 @@ err_put_bio:
        bch2_pagecache_block_put(inode);
        bio_put(bio);
        inode_dio_end(&inode->v);
-       goto err;
+err_put_write_ref:
+       bch2_write_ref_put(c, BCH_WRITE_REF_dio_write);
+       goto out;
 }
 
 void bch2_fs_fs_io_direct_exit(struct bch_fs *c)
index 8c70123b6a0c809b6d50040593281c2e9c115828..20b40477425f49449499b11d63930d92e10ed3ba 100644 (file)
@@ -174,18 +174,18 @@ void __bch2_i_sectors_acct(struct bch_fs *c, struct bch_inode_info *inode,
 static int bch2_flush_inode(struct bch_fs *c,
                            struct bch_inode_info *inode)
 {
-       struct bch_inode_unpacked u;
-       int ret;
-
        if (c->opts.journal_flush_disabled)
                return 0;
 
-       ret = bch2_inode_find_by_inum(c, inode_inum(inode), &u);
-       if (ret)
-               return ret;
+       if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_fsync))
+               return -EROFS;
 
-       return bch2_journal_flush_seq(&c->journal, u.bi_journal_seq) ?:
-               bch2_inode_flush_nocow_writes(c, inode);
+       struct bch_inode_unpacked u;
+       int ret = bch2_inode_find_by_inum(c, inode_inum(inode), &u) ?:
+                 bch2_journal_flush_seq(&c->journal, u.bi_journal_seq) ?:
+                 bch2_inode_flush_nocow_writes(c, inode);
+       bch2_write_ref_put(c, BCH_WRITE_REF_fsync);
+       return ret;
 }
 
 int bch2_fsync(struct file *file, loff_t start, loff_t end, int datasync)
index b5ea9fa1259d1462e9033318466fc914911672ce..fce690007edfce089f054d81cc862c04c132c2b3 100644 (file)
@@ -188,7 +188,8 @@ static struct bch_inode_info *bch2_inode_insert(struct bch_fs *c, struct bch_ino
        BUG_ON(!old);
 
        if (unlikely(old != inode)) {
-               discard_new_inode(&inode->v);
+               __destroy_inode(&inode->v);
+               kmem_cache_free(bch2_inode_cache, inode);
                inode = old;
        } else {
                mutex_lock(&c->vfs_inodes_lock);
@@ -225,8 +226,10 @@ static struct bch_inode_info *bch2_new_inode(struct btree_trans *trans)
 
        if (unlikely(!inode)) {
                int ret = drop_locks_do(trans, (inode = to_bch_ei(new_inode(c->vfs_sb))) ? 0 : -ENOMEM);
-               if (ret && inode)
-                       discard_new_inode(&inode->v);
+               if (ret && inode) {
+                       __destroy_inode(&inode->v);
+                       kmem_cache_free(bch2_inode_cache, inode);
+               }
                if (ret)
                        return ERR_PTR(ret);
        }
index ca4a066e9a5428aa68f88d77f59e9c365a580d6c..0f95d7fb5ec0bddf755299a70908a3520c307f69 100644 (file)
@@ -606,7 +606,7 @@ int bch2_trigger_inode(struct btree_trans *trans,
                       struct bkey_s new,
                       unsigned flags)
 {
-       s64 nr = bkey_is_inode(new.k) - bkey_is_inode(old.k);
+       s64 nr = (s64) bkey_is_inode(new.k) - (s64) bkey_is_inode(old.k);
 
        if (flags & BTREE_TRIGGER_TRANSACTIONAL) {
                if (nr) {
index 725fcf46f6312c267c2a7c05f1eaa6aed5fb83e7..eb1f9d6f5a196e55aebf5b74f485bfa634169da5 100644 (file)
@@ -247,7 +247,7 @@ static void journal_entry_err_msg(struct printbuf *out,
 
        if (entry) {
                prt_str(out, " type=");
-               prt_str(out, bch2_jset_entry_types[entry->type]);
+               bch2_prt_jset_entry_type(out, entry->type);
        }
 
        if (!jset) {
@@ -403,7 +403,8 @@ static void journal_entry_btree_keys_to_text(struct printbuf *out, struct bch_fs
        jset_entry_for_each_key(entry, k) {
                if (!first) {
                        prt_newline(out);
-                       prt_printf(out, "%s: ", bch2_jset_entry_types[entry->type]);
+                       bch2_prt_jset_entry_type(out, entry->type);
+                       prt_str(out, ": ");
                }
                prt_printf(out, "btree=%s l=%u ", bch2_btree_id_str(entry->btree_id), entry->level);
                bch2_bkey_val_to_text(out, c, bkey_i_to_s_c(k));
@@ -563,9 +564,9 @@ static void journal_entry_usage_to_text(struct printbuf *out, struct bch_fs *c,
        struct jset_entry_usage *u =
                container_of(entry, struct jset_entry_usage, entry);
 
-       prt_printf(out, "type=%s v=%llu",
-              bch2_fs_usage_types[u->entry.btree_id],
-              le64_to_cpu(u->v));
+       prt_str(out, "type=");
+       bch2_prt_fs_usage_type(out, u->entry.btree_id);
+       prt_printf(out, " v=%llu", le64_to_cpu(u->v));
 }
 
 static int journal_entry_data_usage_validate(struct bch_fs *c,
@@ -827,11 +828,11 @@ int bch2_journal_entry_validate(struct bch_fs *c,
 void bch2_journal_entry_to_text(struct printbuf *out, struct bch_fs *c,
                                struct jset_entry *entry)
 {
+       bch2_prt_jset_entry_type(out, entry->type);
+
        if (entry->type < BCH_JSET_ENTRY_NR) {
-               prt_printf(out, "%s: ", bch2_jset_entry_types[entry->type]);
+               prt_str(out, ": ");
                bch2_jset_entry_ops[entry->type].to_text(out, c, entry);
-       } else {
-               prt_printf(out, "(unknown type %u)", entry->type);
        }
 }
 
@@ -1722,7 +1723,7 @@ static void journal_write_endio(struct bio *bio)
        percpu_ref_put(&ca->io_ref);
 }
 
-static CLOSURE_CALLBACK(do_journal_write)
+static CLOSURE_CALLBACK(journal_write_submit)
 {
        closure_type(w, struct journal_buf, io);
        struct journal *j = container_of(w, struct journal, buf[w->idx]);
@@ -1767,6 +1768,44 @@ static CLOSURE_CALLBACK(do_journal_write)
        continue_at(cl, journal_write_done, j->wq);
 }
 
+static CLOSURE_CALLBACK(journal_write_preflush)
+{
+       closure_type(w, struct journal_buf, io);
+       struct journal *j = container_of(w, struct journal, buf[w->idx]);
+       struct bch_fs *c = container_of(j, struct bch_fs, journal);
+
+       if (j->seq_ondisk + 1 != le64_to_cpu(w->data->seq)) {
+               spin_lock(&j->lock);
+               closure_wait(&j->async_wait, cl);
+               spin_unlock(&j->lock);
+
+               continue_at(cl, journal_write_preflush, j->wq);
+               return;
+       }
+
+       if (w->separate_flush) {
+               for_each_rw_member(c, ca) {
+                       percpu_ref_get(&ca->io_ref);
+
+                       struct journal_device *ja = &ca->journal;
+                       struct bio *bio = &ja->bio[w->idx]->bio;
+                       bio_reset(bio, ca->disk_sb.bdev,
+                                 REQ_OP_WRITE|REQ_SYNC|REQ_META|REQ_PREFLUSH);
+                       bio->bi_end_io          = journal_write_endio;
+                       bio->bi_private         = ca;
+                       closure_bio_submit(bio, cl);
+               }
+
+               continue_at(cl, journal_write_submit, j->wq);
+       } else {
+               /*
+                * no need to punt to another work item if we're not waiting on
+                * preflushes
+                */
+               journal_write_submit(&cl->work);
+       }
+}
+
 static int bch2_journal_write_prep(struct journal *j, struct journal_buf *w)
 {
        struct bch_fs *c = container_of(j, struct bch_fs, journal);
@@ -2032,23 +2071,9 @@ CLOSURE_CALLBACK(bch2_journal_write)
                goto err;
 
        if (!JSET_NO_FLUSH(w->data))
-               closure_wait_event(&j->async_wait, j->seq_ondisk + 1 == le64_to_cpu(w->data->seq));
-
-       if (!JSET_NO_FLUSH(w->data) && w->separate_flush) {
-               for_each_rw_member(c, ca) {
-                       percpu_ref_get(&ca->io_ref);
-
-                       struct journal_device *ja = &ca->journal;
-                       struct bio *bio = &ja->bio[w->idx]->bio;
-                       bio_reset(bio, ca->disk_sb.bdev,
-                                 REQ_OP_WRITE|REQ_SYNC|REQ_META|REQ_PREFLUSH);
-                       bio->bi_end_io          = journal_write_endio;
-                       bio->bi_private         = ca;
-                       closure_bio_submit(bio, cl);
-               }
-       }
-
-       continue_at(cl, do_journal_write, j->wq);
+               continue_at(cl, journal_write_preflush, j->wq);
+       else
+               continue_at(cl, journal_write_submit, j->wq);
        return;
 no_io:
        continue_at(cl, journal_write_done, j->wq);
index e1800c4119b5fbaf8ebbfcdaef996e1dd9c35ca8..bb068fd724656cf8307d14022ca537f918b65747 100644 (file)
@@ -43,7 +43,7 @@ const char * const __bch2_btree_ids[] = {
        NULL
 };
 
-const char * const bch2_csum_types[] = {
+static const char * const __bch2_csum_types[] = {
        BCH_CSUM_TYPES()
        NULL
 };
@@ -53,7 +53,7 @@ const char * const bch2_csum_opts[] = {
        NULL
 };
 
-const char * const __bch2_compression_types[] = {
+static const char * const __bch2_compression_types[] = {
        BCH_COMPRESSION_TYPES()
        NULL
 };
@@ -83,18 +83,39 @@ const char * const bch2_member_states[] = {
        NULL
 };
 
-const char * const bch2_jset_entry_types[] = {
+static const char * const __bch2_jset_entry_types[] = {
        BCH_JSET_ENTRY_TYPES()
        NULL
 };
 
-const char * const bch2_fs_usage_types[] = {
+static const char * const __bch2_fs_usage_types[] = {
        BCH_FS_USAGE_TYPES()
        NULL
 };
 
 #undef x
 
+static void prt_str_opt_boundscheck(struct printbuf *out, const char * const opts[],
+                                   unsigned nr, const char *type, unsigned idx)
+{
+       if (idx < nr)
+               prt_str(out, opts[idx]);
+       else
+               prt_printf(out, "(unknown %s %u)", type, idx);
+}
+
+#define PRT_STR_OPT_BOUNDSCHECKED(name, type)                                  \
+void bch2_prt_##name(struct printbuf *out, type t)                             \
+{                                                                              \
+       prt_str_opt_boundscheck(out, __bch2_##name##s, ARRAY_SIZE(__bch2_##name##s) - 1, #name, t);\
+}
+
+PRT_STR_OPT_BOUNDSCHECKED(jset_entry_type,     enum bch_jset_entry_type);
+PRT_STR_OPT_BOUNDSCHECKED(fs_usage_type,       enum bch_fs_usage_type);
+PRT_STR_OPT_BOUNDSCHECKED(data_type,           enum bch_data_type);
+PRT_STR_OPT_BOUNDSCHECKED(csum_type,           enum bch_csum_type);
+PRT_STR_OPT_BOUNDSCHECKED(compression_type,    enum bch_compression_type);
+
 static int bch2_opt_fix_errors_parse(struct bch_fs *c, const char *val, u64 *res,
                                     struct printbuf *err)
 {
index 1ac4135cca1c3dccc71a75a0d062ee30df33111c..84e452835a17d84d36c4d0f3906501578bf702d3 100644 (file)
@@ -16,18 +16,20 @@ extern const char * const bch2_version_upgrade_opts[];
 extern const char * const bch2_sb_features[];
 extern const char * const bch2_sb_compat[];
 extern const char * const __bch2_btree_ids[];
-extern const char * const bch2_csum_types[];
 extern const char * const bch2_csum_opts[];
-extern const char * const __bch2_compression_types[];
 extern const char * const bch2_compression_opts[];
 extern const char * const bch2_str_hash_types[];
 extern const char * const bch2_str_hash_opts[];
 extern const char * const __bch2_data_types[];
 extern const char * const bch2_member_states[];
-extern const char * const bch2_jset_entry_types[];
-extern const char * const bch2_fs_usage_types[];
 extern const char * const bch2_d_types[];
 
+void bch2_prt_jset_entry_type(struct printbuf *,       enum bch_jset_entry_type);
+void bch2_prt_fs_usage_type(struct printbuf *,         enum bch_fs_usage_type);
+void bch2_prt_data_type(struct printbuf *,             enum bch_data_type);
+void bch2_prt_csum_type(struct printbuf *,             enum bch_csum_type);
+void bch2_prt_compression_type(struct printbuf *,      enum bch_compression_type);
+
 static inline const char *bch2_d_type_str(unsigned d_type)
 {
        return (d_type < BCH_DT_MAX ? bch2_d_types[d_type] : NULL) ?: "(bad d_type)";
index 0f328aba9760ba0e89fd015ee757239b6d8bd8c4..be5b47619327001ac8191c026575f6ac18d74d16 100644 (file)
@@ -249,7 +249,10 @@ int bch2_journal_replay(struct bch_fs *c)
 
                struct journal_key *k = *kp;
 
-               replay_now_at(j, k->journal_seq);
+               if (k->journal_seq)
+                       replay_now_at(j, k->journal_seq);
+               else
+                       replay_now_at(j, j->replay_journal_seq_end);
 
                ret = commit_do(trans, NULL, NULL,
                                BCH_TRANS_COMMIT_no_enospc|
index cb501460d6152b31a4ae57d9dea6db0792c47c0f..0cec0f7d9703520a3cf24bcc2ca2ce7f86285ebc 100644 (file)
@@ -44,7 +44,7 @@ static int bch2_set_may_go_rw(struct bch_fs *c)
 
        set_bit(BCH_FS_may_go_rw, &c->flags);
 
-       if (keys->nr || c->opts.fsck || !c->sb.clean)
+       if (keys->nr || c->opts.fsck || !c->sb.clean || c->recovery_passes_explicit)
                return bch2_fs_read_write_early(c);
        return 0;
 }
index 5980ba2563fe9fa159ba9d87fe08ab2dc53a78fb..35ca3f138de6fad2428f347c704c03992e2bc05a 100644 (file)
@@ -29,6 +29,14 @@ int bch2_sb_clean_validate_late(struct bch_fs *c, struct bch_sb_field_clean *cle
        for (entry = clean->start;
             entry < (struct jset_entry *) vstruct_end(&clean->field);
             entry = vstruct_next(entry)) {
+               if (vstruct_end(entry) > vstruct_end(&clean->field)) {
+                       bch_err(c, "journal entry (u64s %u) overran end of superblock clean section (u64s %u) by %zu",
+                               le16_to_cpu(entry->u64s), le32_to_cpu(clean->field.u64s),
+                               (u64 *) vstruct_end(entry) - (u64 *) vstruct_end(&clean->field));
+                       bch2_sb_error_count(c, BCH_FSCK_ERR_sb_clean_entry_overrun);
+                       return -BCH_ERR_fsck_repair_unimplemented;
+               }
+
                ret = bch2_journal_entry_validate(c, NULL, entry,
                                                  le16_to_cpu(c->disk_sb.sb->version),
                                                  BCH_SB_BIG_ENDIAN(c->disk_sb.sb),
index d6f81179c3a29b6e884f92c94628d512626c6b45..a98ef940b7a3280bd0da0474ef4f387fdcd0cc18 100644 (file)
          BCH_FSCK_ERR_subvol_fs_path_parent_wrong)             \
        x(btree_subvolume_children,                             \
          BIT_ULL(BCH_RECOVERY_PASS_check_subvols),             \
-         BCH_FSCK_ERR_subvol_children_not_set)
+         BCH_FSCK_ERR_subvol_children_not_set)                 \
+       x(mi_btree_bitmap,                                      \
+         BIT_ULL(BCH_RECOVERY_PASS_check_allocations),         \
+         BCH_FSCK_ERR_btree_bitmap_not_marked)
 
 #define DOWNGRADE_TABLE()
 
index d7d609131030a817c5fa2867fc3cee5796fb898c..06c7a644f4a44279f587a3cffb39473982b3392e 100644 (file)
        x(bucket_gens_nonzero_for_invalid_buckets,              122)    \
        x(need_discard_freespace_key_to_invalid_dev_bucket,     123)    \
        x(need_discard_freespace_key_bad,                       124)    \
-       x(backpointer_pos_wrong,                                125)    \
+       x(backpointer_bucket_offset_wrong,                      125)    \
        x(backpointer_to_missing_device,                        126)    \
        x(backpointer_to_missing_alloc,                         127)    \
        x(backpointer_to_missing_ptr,                           128)    \
        x(btree_ptr_v2_min_key_bad,                             262)    \
        x(btree_root_unreadable_and_scan_found_nothing,         263)    \
        x(snapshot_node_missing,                                264)    \
-       x(dup_backpointer_to_bad_csum_extent,                   265)
+       x(dup_backpointer_to_bad_csum_extent,                   265)    \
+       x(btree_bitmap_not_marked,                              266)    \
+       x(sb_clean_entry_overrun,                               267)
 
 enum bch_sb_error_id {
 #define x(t, n) BCH_FSCK_ERR_##t = n,
index eff5ce18c69c0600047c1fef688a5980af33c678..5b8e621ac5eb5780bb0c2e241196737bc0076e2e 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
 #include "bcachefs.h"
+#include "btree_cache.h"
 #include "disk_groups.h"
 #include "opts.h"
 #include "replicas.h"
@@ -426,3 +427,55 @@ void bch2_dev_errors_reset(struct bch_dev *ca)
        bch2_write_super(c);
        mutex_unlock(&c->sb_lock);
 }
+
+/*
+ * Per member "range has btree nodes" bitmap:
+ *
+ * This is so that if we ever have to run the btree node scan to repair we don't
+ * have to scan full devices:
+ */
+
+bool bch2_dev_btree_bitmap_marked(struct bch_fs *c, struct bkey_s_c k)
+{
+       bkey_for_each_ptr(bch2_bkey_ptrs_c(k), ptr)
+               if (!bch2_dev_btree_bitmap_marked_sectors(bch_dev_bkey_exists(c, ptr->dev),
+                                                         ptr->offset, btree_sectors(c)))
+                       return false;
+       return true;
+}
+
+static void __bch2_dev_btree_bitmap_mark(struct bch_sb_field_members_v2 *mi, unsigned dev,
+                               u64 start, unsigned sectors)
+{
+       struct bch_member *m = __bch2_members_v2_get_mut(mi, dev);
+       u64 bitmap = le64_to_cpu(m->btree_allocated_bitmap);
+
+       u64 end = start + sectors;
+
+       int resize = ilog2(roundup_pow_of_two(end)) - (m->btree_bitmap_shift + 6);
+       if (resize > 0) {
+               u64 new_bitmap = 0;
+
+               for (unsigned i = 0; i < 64; i++)
+                       if (bitmap & BIT_ULL(i))
+                               new_bitmap |= BIT_ULL(i >> resize);
+               bitmap = new_bitmap;
+               m->btree_bitmap_shift += resize;
+       }
+
+       for (unsigned bit = start >> m->btree_bitmap_shift;
+            (u64) bit << m->btree_bitmap_shift < end;
+            bit++)
+               bitmap |= BIT_ULL(bit);
+
+       m->btree_allocated_bitmap = cpu_to_le64(bitmap);
+}
+
+void bch2_dev_btree_bitmap_mark(struct bch_fs *c, struct bkey_s_c k)
+{
+       lockdep_assert_held(&c->sb_lock);
+
+       struct bch_sb_field_members_v2 *mi = bch2_sb_field_get(c->disk_sb.sb, members_v2);
+       bkey_for_each_ptr(bch2_bkey_ptrs_c(k), ptr)
+               __bch2_dev_btree_bitmap_mark(mi, ptr->dev, ptr->offset, btree_sectors(c));
+}
index be0a941832715a32634b8c3dea60bbf1685a672f..5efa64eca5f85af5637faa12aa85b83fbcde6ad3 100644 (file)
@@ -3,6 +3,7 @@
 #define _BCACHEFS_SB_MEMBERS_H
 
 #include "darray.h"
+#include "bkey_types.h"
 
 extern char * const bch2_member_error_strs[];
 
@@ -220,6 +221,8 @@ static inline struct bch_member_cpu bch2_mi_to_cpu(struct bch_member *mi)
                        : 1,
                .freespace_initialized = BCH_MEMBER_FREESPACE_INITIALIZED(mi),
                .valid          = bch2_member_exists(mi),
+               .btree_bitmap_shift     = mi->btree_bitmap_shift,
+               .btree_allocated_bitmap = le64_to_cpu(mi->btree_allocated_bitmap),
        };
 }
 
@@ -228,4 +231,22 @@ void bch2_sb_members_from_cpu(struct bch_fs *);
 void bch2_dev_io_errors_to_text(struct printbuf *, struct bch_dev *);
 void bch2_dev_errors_reset(struct bch_dev *);
 
+static inline bool bch2_dev_btree_bitmap_marked_sectors(struct bch_dev *ca, u64 start, unsigned sectors)
+{
+       u64 end = start + sectors;
+
+       if (end > 64ULL << ca->mi.btree_bitmap_shift)
+               return false;
+
+       for (unsigned bit = start >> ca->mi.btree_bitmap_shift;
+            (u64) bit << ca->mi.btree_bitmap_shift < end;
+            bit++)
+               if (!(ca->mi.btree_allocated_bitmap & BIT_ULL(bit)))
+                       return false;
+       return true;
+}
+
+bool bch2_dev_btree_bitmap_marked(struct bch_fs *, struct bkey_s_c);
+void bch2_dev_btree_bitmap_mark(struct bch_fs *, struct bkey_s_c);
+
 #endif /* _BCACHEFS_SB_MEMBERS_H */
index 5eee055ee2721a3967fb31ca38adcbc5672521d6..08ea3dbbbe97ce11833fe79baa5fd87935919339 100644 (file)
@@ -700,8 +700,11 @@ retry:
                return -ENOMEM;
 
        sb->sb_name = kstrdup(path, GFP_KERNEL);
-       if (!sb->sb_name)
-               return -ENOMEM;
+       if (!sb->sb_name) {
+               ret = -ENOMEM;
+               prt_printf(&err, "error allocating memory for sb_name");
+               goto err;
+       }
 
 #ifndef __KERNEL__
        if (opt_get(*opts, direct_io) == false)
index 8daf80a38d60c6e4fa97b97345d3d4ecb80e7e88..88e214c609bb2b6beab65b604acf1053596f3a8a 100644 (file)
@@ -544,6 +544,7 @@ static void __bch2_fs_free(struct bch_fs *c)
 
        bch2_find_btree_nodes_exit(&c->found_btree_nodes);
        bch2_free_pending_node_rewrites(c);
+       bch2_fs_allocator_background_exit(c);
        bch2_fs_sb_errors_exit(c);
        bch2_fs_counters_exit(c);
        bch2_fs_snapshots_exit(c);
index ec784d975f6655a378207692644975e53271ddca..11bcef170c2c22644108e9fbec9b24eaf478059c 100644 (file)
@@ -37,6 +37,8 @@ struct bch_member_cpu {
        u8                      durability;
        u8                      freespace_initialized;
        u8                      valid;
+       u8                      btree_bitmap_shift;
+       u64                     btree_allocated_bitmap;
 };
 
 #endif /* _BCACHEFS_SUPER_TYPES_H */
index b18b0cc81b594ad6144b43599418418a1caf5e95..5be92fe3f4ea4e115512f0b7a31482919406a507 100644 (file)
@@ -25,6 +25,7 @@
 #include "ec.h"
 #include "inode.h"
 #include "journal.h"
+#include "journal_reclaim.h"
 #include "keylist.h"
 #include "move.h"
 #include "movinggc.h"
@@ -138,6 +139,7 @@ do {                                                                        \
 write_attribute(trigger_gc);
 write_attribute(trigger_discards);
 write_attribute(trigger_invalidates);
+write_attribute(trigger_journal_flush);
 write_attribute(prune_cache);
 write_attribute(btree_wakeup);
 rw_attribute(btree_gc_periodic);
@@ -500,7 +502,7 @@ STORE(bch2_fs)
 
        /* Debugging: */
 
-       if (!test_bit(BCH_FS_rw, &c->flags))
+       if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_sysfs))
                return -EROFS;
 
        if (attr == &sysfs_prune_cache) {
@@ -533,6 +535,11 @@ STORE(bch2_fs)
        if (attr == &sysfs_trigger_invalidates)
                bch2_do_invalidates(c);
 
+       if (attr == &sysfs_trigger_journal_flush) {
+               bch2_journal_flush_all_pins(&c->journal);
+               bch2_journal_meta(&c->journal);
+       }
+
 #ifdef CONFIG_BCACHEFS_TESTS
        if (attr == &sysfs_perf_test) {
                char *tmp = kstrdup(buf, GFP_KERNEL), *p = tmp;
@@ -553,6 +560,7 @@ STORE(bch2_fs)
                        size = ret;
        }
 #endif
+       bch2_write_ref_put(c, BCH_WRITE_REF_sysfs);
        return size;
 }
 SYSFS_OPS(bch2_fs);
@@ -651,6 +659,7 @@ struct attribute *bch2_fs_internal_files[] = {
        &sysfs_trigger_gc,
        &sysfs_trigger_discards,
        &sysfs_trigger_invalidates,
+       &sysfs_trigger_journal_flush,
        &sysfs_prune_cache,
        &sysfs_btree_wakeup,
 
index 940db15d6a939bf93281627e9759904e4a6531f3..b1af7ac430f662aa2b827d0c6550ef6187089352 100644 (file)
@@ -294,16 +294,27 @@ static int thread_with_stdio_fn(void *arg)
        return 0;
 }
 
-int bch2_run_thread_with_stdio(struct thread_with_stdio *thr,
-                              const struct thread_with_stdio_ops *ops)
+void bch2_thread_with_stdio_init(struct thread_with_stdio *thr,
+                                const struct thread_with_stdio_ops *ops)
 {
        stdio_buf_init(&thr->stdio.input);
        stdio_buf_init(&thr->stdio.output);
        thr->ops = ops;
+}
 
+int __bch2_run_thread_with_stdio(struct thread_with_stdio *thr)
+{
        return bch2_run_thread_with_file(&thr->thr, &thread_with_stdio_fops, thread_with_stdio_fn);
 }
 
+int bch2_run_thread_with_stdio(struct thread_with_stdio *thr,
+                              const struct thread_with_stdio_ops *ops)
+{
+       bch2_thread_with_stdio_init(thr, ops);
+
+       return __bch2_run_thread_with_stdio(thr);
+}
+
 int bch2_run_thread_with_stdout(struct thread_with_stdio *thr,
                                const struct thread_with_stdio_ops *ops)
 {
index af54ea8f5b0ff85871c915e275187c29b7b0c6f1..1d63d14d7dcae811a21e49a0cc509407daf7584c 100644 (file)
@@ -63,6 +63,9 @@ struct thread_with_stdio {
        const struct thread_with_stdio_ops      *ops;
 };
 
+void bch2_thread_with_stdio_init(struct thread_with_stdio *,
+                                const struct thread_with_stdio_ops *);
+int __bch2_run_thread_with_stdio(struct thread_with_stdio *);
 int bch2_run_thread_with_stdio(struct thread_with_stdio *,
                               const struct thread_with_stdio_ops *);
 int bch2_run_thread_with_stdout(struct thread_with_stdio *,
index c1e6a5bbeeaffe16b93846d5c8c0e90d4cc37659..58110c96866736ad9bf74b0e40c42e3bd9de81a3 100644 (file)
@@ -2776,20 +2776,14 @@ struct btrfs_data_container *init_data_container(u32 total_bytes)
        size_t alloc_bytes;
 
        alloc_bytes = max_t(size_t, total_bytes, sizeof(*data));
-       data = kvmalloc(alloc_bytes, GFP_KERNEL);
+       data = kvzalloc(alloc_bytes, GFP_KERNEL);
        if (!data)
                return ERR_PTR(-ENOMEM);
 
-       if (total_bytes >= sizeof(*data)) {
+       if (total_bytes >= sizeof(*data))
                data->bytes_left = total_bytes - sizeof(*data);
-               data->bytes_missing = 0;
-       } else {
+       else
                data->bytes_missing = sizeof(*data) - total_bytes;
-               data->bytes_left = 0;
-       }
-
-       data->elem_cnt = 0;
-       data->elem_missed = 0;
 
        return data;
 }
index beedd6ed64d39bd7f53ad814c22df36b80b96235..257d044bca9158c95e205ff22ff0d662d0d7f074 100644 (file)
@@ -3464,6 +3464,14 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
        if (root_id != BTRFS_TREE_LOG_OBJECTID) {
                struct btrfs_ref generic_ref = { 0 };
 
+               /*
+                * Assert that the extent buffer is not cleared due to
+                * EXTENT_BUFFER_ZONED_ZEROOUT. Please refer
+                * btrfs_clear_buffer_dirty() and btree_csum_one_bio() for
+                * detail.
+                */
+               ASSERT(btrfs_header_bytenr(buf) != 0);
+
                btrfs_init_generic_ref(&generic_ref, BTRFS_DROP_DELAYED_REF,
                                       buf->start, buf->len, parent,
                                       btrfs_header_owner(buf));
index 61594eaf1f8969fc3ba04604e3470a8932450767..2776112dbdf8d471a7cb4d515fdd443e6fadbac5 100644 (file)
@@ -681,31 +681,21 @@ static void end_bbio_data_read(struct btrfs_bio *bbio)
 int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array,
                           gfp_t extra_gfp)
 {
+       const gfp_t gfp = GFP_NOFS | extra_gfp;
        unsigned int allocated;
 
        for (allocated = 0; allocated < nr_pages;) {
                unsigned int last = allocated;
 
-               allocated = alloc_pages_bulk_array(GFP_NOFS | extra_gfp,
-                                                  nr_pages, page_array);
-
-               if (allocated == nr_pages)
-                       return 0;
-
-               /*
-                * During this iteration, no page could be allocated, even
-                * though alloc_pages_bulk_array() falls back to alloc_page()
-                * if  it could not bulk-allocate. So we must be out of memory.
-                */
-               if (allocated == last) {
+               allocated = alloc_pages_bulk_array(gfp, nr_pages, page_array);
+               if (unlikely(allocated == last)) {
+                       /* No progress, fail and do cleanup. */
                        for (int i = 0; i < allocated; i++) {
                                __free_page(page_array[i]);
                                page_array[i] = NULL;
                        }
                        return -ENOMEM;
                }
-
-               memalloc_retry_wait(GFP_NOFS);
        }
        return 0;
 }
@@ -4154,7 +4144,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans,
         * The actual zeroout of the buffer will happen later in
         * btree_csum_one_bio.
         */
-       if (btrfs_is_zoned(fs_info)) {
+       if (btrfs_is_zoned(fs_info) && test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) {
                set_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags);
                return;
        }
@@ -4193,6 +4183,7 @@ void set_extent_buffer_dirty(struct extent_buffer *eb)
        num_folios = num_extent_folios(eb);
        WARN_ON(atomic_read(&eb->refs) == 0);
        WARN_ON(!test_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags));
+       WARN_ON(test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags));
 
        if (!was_dirty) {
                bool subpage = eb->fs_info->nodesize < PAGE_SIZE;
index 445f7716f1e2f70b3f780e7c1f03d020f0eb6346..24a048210b15719db5ae76f09ac114e227ff0ac0 100644 (file)
@@ -817,7 +817,7 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end,
                                        split->block_len = em->block_len;
                                        split->orig_start = em->orig_start;
                                } else {
-                                       const u64 diff = start + len - em->start;
+                                       const u64 diff = end - em->start;
 
                                        split->block_len = split->len;
                                        split->block_start += diff;
index c65fe5de40220d3b51003bb73b3e6414eaefba08..7fed887e700c4e8e07b6ff7932434a384790b8da 100644 (file)
@@ -1145,13 +1145,13 @@ static void submit_one_async_extent(struct async_chunk *async_chunk,
                                   0, *alloc_hint, &ins, 1, 1);
        if (ret) {
                /*
-                * Here we used to try again by going back to non-compressed
-                * path for ENOSPC.  But we can't reserve space even for
-                * compressed size, how could it work for uncompressed size
-                * which requires larger size?  So here we directly go error
-                * path.
+                * We can't reserve contiguous space for the compressed size.
+                * Unlikely, but it's possible that we could have enough
+                * non-contiguous space for the uncompressed size instead.  So
+                * fall back to uncompressed.
                 */
-               goto out_free;
+               submit_uncompressed_range(inode, async_extent, locked_page);
+               goto done;
        }
 
        /* Here we're doing allocation and writeback of the compressed pages */
@@ -1203,7 +1203,6 @@ done:
 out_free_reserve:
        btrfs_dec_block_group_reservations(fs_info, ins.objectid);
        btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 1);
-out_free:
        mapping_set_error(inode->vfs_inode.i_mapping, -EIO);
        extent_clear_unlock_delalloc(inode, start, end,
                                     NULL, EXTENT_LOCKED | EXTENT_DELALLOC |
index 55f3ba6a831ca194e2d8405dbf7caa60fbd81dfc..0493272a7668ed0eb0104284e572503855645ca8 100644 (file)
@@ -3758,15 +3758,43 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
                goto drop_write;
        }
 
-       down_write(&fs_info->subvol_sem);
-
        switch (sa->cmd) {
        case BTRFS_QUOTA_CTL_ENABLE:
        case BTRFS_QUOTA_CTL_ENABLE_SIMPLE_QUOTA:
+               down_write(&fs_info->subvol_sem);
                ret = btrfs_quota_enable(fs_info, sa);
+               up_write(&fs_info->subvol_sem);
                break;
        case BTRFS_QUOTA_CTL_DISABLE:
+               /*
+                * Lock the cleaner mutex to prevent races with concurrent
+                * relocation, because relocation may be building backrefs for
+                * blocks of the quota root while we are deleting the root. This
+                * is like dropping fs roots of deleted snapshots/subvolumes, we
+                * need the same protection.
+                *
+                * This also prevents races between concurrent tasks trying to
+                * disable quotas, because we will unlock and relock
+                * qgroup_ioctl_lock across BTRFS_FS_QUOTA_ENABLED changes.
+                *
+                * We take this here because we have the dependency of
+                *
+                * inode_lock -> subvol_sem
+                *
+                * because of rename.  With relocation we can prealloc extents,
+                * so that makes the dependency chain
+                *
+                * cleaner_mutex -> inode_lock -> subvol_sem
+                *
+                * so we must take the cleaner_mutex here before we take the
+                * subvol_sem.  The deadlock can't actually happen, but this
+                * quiets lockdep.
+                */
+               mutex_lock(&fs_info->cleaner_mutex);
+               down_write(&fs_info->subvol_sem);
                ret = btrfs_quota_disable(fs_info);
+               up_write(&fs_info->subvol_sem);
+               mutex_unlock(&fs_info->cleaner_mutex);
                break;
        default:
                ret = -EINVAL;
@@ -3774,7 +3802,6 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
        }
 
        kfree(sa);
-       up_write(&fs_info->subvol_sem);
 drop_write:
        mnt_drop_write_file(file);
        return ret;
index c96dd66fd0f7224c9a413c4d61d51420c5a9060b..210d9c82e2ae05976fc75325562f25cd7f9dc0b2 100644 (file)
@@ -7,7 +7,7 @@
 
 #ifdef CONFIG_PRINTK
 
-#define STATE_STRING_PREFACE   ": state "
+#define STATE_STRING_PREFACE   " state "
 #define STATE_STRING_BUF_LEN   (sizeof(STATE_STRING_PREFACE) + BTRFS_FS_STATE_COUNT + 1)
 
 /*
index b749ba45da2ba2b13d75695e882ab343dda9439c..c2a42bcde98e0ee4edc4ed171f44800cf53d7284 100644 (file)
@@ -1188,6 +1188,7 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent(
        ordered->disk_bytenr += len;
        ordered->num_bytes -= len;
        ordered->disk_num_bytes -= len;
+       ordered->ram_bytes -= len;
 
        if (test_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags)) {
                ASSERT(ordered->bytes_left == 0);
index cf8820ce7aa2979920c6daafc1071c26571ecee6..364acc9bbe730c131a3e4f9b6c8387e6645e300a 100644 (file)
@@ -1342,16 +1342,10 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
        lockdep_assert_held_write(&fs_info->subvol_sem);
 
        /*
-        * Lock the cleaner mutex to prevent races with concurrent relocation,
-        * because relocation may be building backrefs for blocks of the quota
-        * root while we are deleting the root. This is like dropping fs roots
-        * of deleted snapshots/subvolumes, we need the same protection.
-        *
-        * This also prevents races between concurrent tasks trying to disable
-        * quotas, because we will unlock and relock qgroup_ioctl_lock across
-        * BTRFS_FS_QUOTA_ENABLED changes.
+        * Relocation will mess with backrefs, so make sure we have the
+        * cleaner_mutex held to protect us from relocate.
         */
-       mutex_lock(&fs_info->cleaner_mutex);
+       lockdep_assert_held(&fs_info->cleaner_mutex);
 
        mutex_lock(&fs_info->qgroup_ioctl_lock);
        if (!fs_info->quota_root)
@@ -1373,9 +1367,13 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
        clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
        btrfs_qgroup_wait_for_completion(fs_info, false);
 
+       /*
+        * We have nothing held here and no trans handle, just return the error
+        * if there is one.
+        */
        ret = flush_reservations(fs_info);
        if (ret)
-               goto out_unlock_cleaner;
+               return ret;
 
        /*
         * 1 For the root item
@@ -1439,9 +1437,6 @@ out:
                btrfs_end_transaction(trans);
        else if (trans)
                ret = btrfs_commit_transaction(trans);
-out_unlock_cleaner:
-       mutex_unlock(&fs_info->cleaner_mutex);
-
        return ret;
 }
 
index fa25004ab04e7b28d73dee024303c0dab4077db6..4b22cfe9a98cb0244288d0a961fc7f0e1c7daf4e 100644 (file)
@@ -1012,6 +1012,7 @@ static void scrub_stripe_read_repair_worker(struct work_struct *work)
        struct btrfs_fs_info *fs_info = sctx->fs_info;
        int num_copies = btrfs_num_copies(fs_info, stripe->bg->start,
                                          stripe->bg->length);
+       unsigned long repaired;
        int mirror;
        int i;
 
@@ -1078,16 +1079,15 @@ out:
         * Submit the repaired sectors.  For zoned case, we cannot do repair
         * in-place, but queue the bg to be relocated.
         */
-       if (btrfs_is_zoned(fs_info)) {
-               if (!bitmap_empty(&stripe->error_bitmap, stripe->nr_sectors))
+       bitmap_andnot(&repaired, &stripe->init_error_bitmap, &stripe->error_bitmap,
+                     stripe->nr_sectors);
+       if (!sctx->readonly && !bitmap_empty(&repaired, stripe->nr_sectors)) {
+               if (btrfs_is_zoned(fs_info)) {
                        btrfs_repair_one_zone(fs_info, sctx->stripes[0].bg->start);
-       } else if (!sctx->readonly) {
-               unsigned long repaired;
-
-               bitmap_andnot(&repaired, &stripe->init_error_bitmap,
-                             &stripe->error_bitmap, stripe->nr_sectors);
-               scrub_write_sectors(sctx, stripe, repaired, false);
-               wait_scrub_stripe_io(stripe);
+               } else {
+                       scrub_write_sectors(sctx, stripe, repaired, false);
+                       wait_scrub_stripe_io(stripe);
+               }
        }
 
        scrub_stripe_report_errors(sctx, stripe);
index 253cce7ffecfe5acaa81d9b574f8398f5c134300..47b5d301038eed0f040958771b8846ecbd672f65 100644 (file)
@@ -847,6 +847,11 @@ static int test_case_7(struct btrfs_fs_info *fs_info)
                goto out;
        }
 
+       if (em->block_start != SZ_32K + SZ_4K) {
+               test_err("em->block_start is %llu, expected 36K", em->block_start);
+               goto out;
+       }
+
        free_extent_map(em);
 
        read_lock(&em_tree->lock);
index f15591f3e54fa4cd7e92103e17b0ae74eb1a54f9..ef6bd2f4251b523ecfa4e0c31fc3c7eb0d26d332 100644 (file)
@@ -3455,6 +3455,7 @@ again:
                         * alignment and size).
                         */
                        ret = -EUCLEAN;
+                       mutex_unlock(&fs_info->reclaim_bgs_lock);
                        goto error;
                }
 
index 8aff1a724805a67ad3733fbce2127a39e563e01d..62da538d91cbd47cea44f4d021096c6a3a654908 100644 (file)
@@ -151,7 +151,7 @@ static int erofs_fscache_read_io_async(struct fscache_cookie *cookie,
                if (WARN_ON(len == 0))
                        source = NETFS_INVALID_READ;
                if (source != NETFS_READ_FROM_CACHE) {
-                       erofs_err(NULL, "prepare_read failed (source %d)", source);
+                       erofs_err(NULL, "prepare_ondemand_read failed (source %d)", source);
                        return -EIO;
                }
 
index 39c67119f43bfd762aa204a1edcaa77916f5fb76..d28ccfc0352b1ae4728fb25fdf8672bd0ee81789 100644 (file)
@@ -84,13 +84,6 @@ struct erofs_dev_context {
        bool flatdev;
 };
 
-struct erofs_fs_context {
-       struct erofs_mount_opts opt;
-       struct erofs_dev_context *devs;
-       char *fsid;
-       char *domain_id;
-};
-
 /* all filesystem-wide lz4 configurations */
 struct erofs_sb_lz4_info {
        /* # of pages needed for EROFS lz4 rolling decompression */
index c0eb139adb07a8ce852edd56370a79e5760036d9..30b49b2eee53409a0b4b293a4ff579eceb2d5087 100644 (file)
@@ -370,18 +370,18 @@ out:
        return ret;
 }
 
-static void erofs_default_options(struct erofs_fs_context *ctx)
+static void erofs_default_options(struct erofs_sb_info *sbi)
 {
 #ifdef CONFIG_EROFS_FS_ZIP
-       ctx->opt.cache_strategy = EROFS_ZIP_CACHE_READAROUND;
-       ctx->opt.max_sync_decompress_pages = 3;
-       ctx->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_AUTO;
+       sbi->opt.cache_strategy = EROFS_ZIP_CACHE_READAROUND;
+       sbi->opt.max_sync_decompress_pages = 3;
+       sbi->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_AUTO;
 #endif
 #ifdef CONFIG_EROFS_FS_XATTR
-       set_opt(&ctx->opt, XATTR_USER);
+       set_opt(&sbi->opt, XATTR_USER);
 #endif
 #ifdef CONFIG_EROFS_FS_POSIX_ACL
-       set_opt(&ctx->opt, POSIX_ACL);
+       set_opt(&sbi->opt, POSIX_ACL);
 #endif
 }
 
@@ -426,16 +426,16 @@ static const struct fs_parameter_spec erofs_fs_parameters[] = {
 static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode)
 {
 #ifdef CONFIG_FS_DAX
-       struct erofs_fs_context *ctx = fc->fs_private;
+       struct erofs_sb_info *sbi = fc->s_fs_info;
 
        switch (mode) {
        case EROFS_MOUNT_DAX_ALWAYS:
-               set_opt(&ctx->opt, DAX_ALWAYS);
-               clear_opt(&ctx->opt, DAX_NEVER);
+               set_opt(&sbi->opt, DAX_ALWAYS);
+               clear_opt(&sbi->opt, DAX_NEVER);
                return true;
        case EROFS_MOUNT_DAX_NEVER:
-               set_opt(&ctx->opt, DAX_NEVER);
-               clear_opt(&ctx->opt, DAX_ALWAYS);
+               set_opt(&sbi->opt, DAX_NEVER);
+               clear_opt(&sbi->opt, DAX_ALWAYS);
                return true;
        default:
                DBG_BUGON(1);
@@ -450,7 +450,7 @@ static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode)
 static int erofs_fc_parse_param(struct fs_context *fc,
                                struct fs_parameter *param)
 {
-       struct erofs_fs_context *ctx = fc->fs_private;
+       struct erofs_sb_info *sbi = fc->s_fs_info;
        struct fs_parse_result result;
        struct erofs_device_info *dif;
        int opt, ret;
@@ -463,9 +463,9 @@ static int erofs_fc_parse_param(struct fs_context *fc,
        case Opt_user_xattr:
 #ifdef CONFIG_EROFS_FS_XATTR
                if (result.boolean)
-                       set_opt(&ctx->opt, XATTR_USER);
+                       set_opt(&sbi->opt, XATTR_USER);
                else
-                       clear_opt(&ctx->opt, XATTR_USER);
+                       clear_opt(&sbi->opt, XATTR_USER);
 #else
                errorfc(fc, "{,no}user_xattr options not supported");
 #endif
@@ -473,16 +473,16 @@ static int erofs_fc_parse_param(struct fs_context *fc,
        case Opt_acl:
 #ifdef CONFIG_EROFS_FS_POSIX_ACL
                if (result.boolean)
-                       set_opt(&ctx->opt, POSIX_ACL);
+                       set_opt(&sbi->opt, POSIX_ACL);
                else
-                       clear_opt(&ctx->opt, POSIX_ACL);
+                       clear_opt(&sbi->opt, POSIX_ACL);
 #else
                errorfc(fc, "{,no}acl options not supported");
 #endif
                break;
        case Opt_cache_strategy:
 #ifdef CONFIG_EROFS_FS_ZIP
-               ctx->opt.cache_strategy = result.uint_32;
+               sbi->opt.cache_strategy = result.uint_32;
 #else
                errorfc(fc, "compression not supported, cache_strategy ignored");
 #endif
@@ -504,27 +504,27 @@ static int erofs_fc_parse_param(struct fs_context *fc,
                        kfree(dif);
                        return -ENOMEM;
                }
-               down_write(&ctx->devs->rwsem);
-               ret = idr_alloc(&ctx->devs->tree, dif, 0, 0, GFP_KERNEL);
-               up_write(&ctx->devs->rwsem);
+               down_write(&sbi->devs->rwsem);
+               ret = idr_alloc(&sbi->devs->tree, dif, 0, 0, GFP_KERNEL);
+               up_write(&sbi->devs->rwsem);
                if (ret < 0) {
                        kfree(dif->path);
                        kfree(dif);
                        return ret;
                }
-               ++ctx->devs->extra_devices;
+               ++sbi->devs->extra_devices;
                break;
 #ifdef CONFIG_EROFS_FS_ONDEMAND
        case Opt_fsid:
-               kfree(ctx->fsid);
-               ctx->fsid = kstrdup(param->string, GFP_KERNEL);
-               if (!ctx->fsid)
+               kfree(sbi->fsid);
+               sbi->fsid = kstrdup(param->string, GFP_KERNEL);
+               if (!sbi->fsid)
                        return -ENOMEM;
                break;
        case Opt_domain_id:
-               kfree(ctx->domain_id);
-               ctx->domain_id = kstrdup(param->string, GFP_KERNEL);
-               if (!ctx->domain_id)
+               kfree(sbi->domain_id);
+               sbi->domain_id = kstrdup(param->string, GFP_KERNEL);
+               if (!sbi->domain_id)
                        return -ENOMEM;
                break;
 #else
@@ -581,8 +581,7 @@ static const struct export_operations erofs_export_ops = {
 static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
 {
        struct inode *inode;
-       struct erofs_sb_info *sbi;
-       struct erofs_fs_context *ctx = fc->fs_private;
+       struct erofs_sb_info *sbi = EROFS_SB(sb);
        int err;
 
        sb->s_magic = EROFS_SUPER_MAGIC;
@@ -590,19 +589,6 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
        sb->s_maxbytes = MAX_LFS_FILESIZE;
        sb->s_op = &erofs_sops;
 
-       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-       if (!sbi)
-               return -ENOMEM;
-
-       sb->s_fs_info = sbi;
-       sbi->opt = ctx->opt;
-       sbi->devs = ctx->devs;
-       ctx->devs = NULL;
-       sbi->fsid = ctx->fsid;
-       ctx->fsid = NULL;
-       sbi->domain_id = ctx->domain_id;
-       ctx->domain_id = NULL;
-
        sbi->blkszbits = PAGE_SHIFT;
        if (erofs_is_fscache_mode(sb)) {
                sb->s_blocksize = PAGE_SIZE;
@@ -706,9 +692,9 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
 
 static int erofs_fc_get_tree(struct fs_context *fc)
 {
-       struct erofs_fs_context *ctx = fc->fs_private;
+       struct erofs_sb_info *sbi = fc->s_fs_info;
 
-       if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && ctx->fsid)
+       if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid)
                return get_tree_nodev(fc, erofs_fc_fill_super);
 
        return get_tree_bdev(fc, erofs_fc_fill_super);
@@ -718,19 +704,19 @@ static int erofs_fc_reconfigure(struct fs_context *fc)
 {
        struct super_block *sb = fc->root->d_sb;
        struct erofs_sb_info *sbi = EROFS_SB(sb);
-       struct erofs_fs_context *ctx = fc->fs_private;
+       struct erofs_sb_info *new_sbi = fc->s_fs_info;
 
        DBG_BUGON(!sb_rdonly(sb));
 
-       if (ctx->fsid || ctx->domain_id)
+       if (new_sbi->fsid || new_sbi->domain_id)
                erofs_info(sb, "ignoring reconfiguration for fsid|domain_id.");
 
-       if (test_opt(&ctx->opt, POSIX_ACL))
+       if (test_opt(&new_sbi->opt, POSIX_ACL))
                fc->sb_flags |= SB_POSIXACL;
        else
                fc->sb_flags &= ~SB_POSIXACL;
 
-       sbi->opt = ctx->opt;
+       sbi->opt = new_sbi->opt;
 
        fc->sb_flags |= SB_RDONLY;
        return 0;
@@ -761,12 +747,15 @@ static void erofs_free_dev_context(struct erofs_dev_context *devs)
 
 static void erofs_fc_free(struct fs_context *fc)
 {
-       struct erofs_fs_context *ctx = fc->fs_private;
+       struct erofs_sb_info *sbi = fc->s_fs_info;
 
-       erofs_free_dev_context(ctx->devs);
-       kfree(ctx->fsid);
-       kfree(ctx->domain_id);
-       kfree(ctx);
+       if (!sbi)
+               return;
+
+       erofs_free_dev_context(sbi->devs);
+       kfree(sbi->fsid);
+       kfree(sbi->domain_id);
+       kfree(sbi);
 }
 
 static const struct fs_context_operations erofs_context_ops = {
@@ -778,38 +767,35 @@ static const struct fs_context_operations erofs_context_ops = {
 
 static int erofs_init_fs_context(struct fs_context *fc)
 {
-       struct erofs_fs_context *ctx;
+       struct erofs_sb_info *sbi;
 
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx)
+       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
+       if (!sbi)
                return -ENOMEM;
-       ctx->devs = kzalloc(sizeof(struct erofs_dev_context), GFP_KERNEL);
-       if (!ctx->devs) {
-               kfree(ctx);
+
+       sbi->devs = kzalloc(sizeof(struct erofs_dev_context), GFP_KERNEL);
+       if (!sbi->devs) {
+               kfree(sbi);
                return -ENOMEM;
        }
-       fc->fs_private = ctx;
+       fc->s_fs_info = sbi;
 
-       idr_init(&ctx->devs->tree);
-       init_rwsem(&ctx->devs->rwsem);
-       erofs_default_options(ctx);
+       idr_init(&sbi->devs->tree);
+       init_rwsem(&sbi->devs->rwsem);
+       erofs_default_options(sbi);
        fc->ops = &erofs_context_ops;
        return 0;
 }
 
 static void erofs_kill_sb(struct super_block *sb)
 {
-       struct erofs_sb_info *sbi;
+       struct erofs_sb_info *sbi = EROFS_SB(sb);
 
-       if (erofs_is_fscache_mode(sb))
+       if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid)
                kill_anon_super(sb);
        else
                kill_block_super(sb);
 
-       sbi = EROFS_SB(sb);
-       if (!sbi)
-               return;
-
        erofs_free_dev_context(sbi->devs);
        fs_put_dax(sbi->dax_dev, NULL);
        erofs_fscache_unregister_fs(sb);
index 882b89edc52adb24e6f62dc2b778e186001293d4..f53ca4f7fceddd0b0e661f05105435b420e19430 100644 (file)
@@ -979,6 +979,34 @@ static __poll_t __ep_eventpoll_poll(struct file *file, poll_table *wait, int dep
        return res;
 }
 
+/*
+ * The ffd.file pointer may be in the process of being torn down due to
+ * being closed, but we may not have finished eventpoll_release() yet.
+ *
+ * Normally, even with the atomic_long_inc_not_zero, the file may have
+ * been free'd and then gotten re-allocated to something else (since
+ * files are not RCU-delayed, they are SLAB_TYPESAFE_BY_RCU).
+ *
+ * But for epoll, users hold the ep->mtx mutex, and as such any file in
+ * the process of being free'd will block in eventpoll_release_file()
+ * and thus the underlying file allocation will not be free'd, and the
+ * file re-use cannot happen.
+ *
+ * For the same reason we can avoid a rcu_read_lock() around the
+ * operation - 'ffd.file' cannot go away even if the refcount has
+ * reached zero (but we must still not call out to ->poll() functions
+ * etc).
+ */
+static struct file *epi_fget(const struct epitem *epi)
+{
+       struct file *file;
+
+       file = epi->ffd.file;
+       if (!atomic_long_inc_not_zero(&file->f_count))
+               file = NULL;
+       return file;
+}
+
 /*
  * Differs from ep_eventpoll_poll() in that internal callers already have
  * the ep->mtx so we need to start from depth=1, such that mutex_lock_nested()
@@ -987,14 +1015,22 @@ static __poll_t __ep_eventpoll_poll(struct file *file, poll_table *wait, int dep
 static __poll_t ep_item_poll(const struct epitem *epi, poll_table *pt,
                                 int depth)
 {
-       struct file *file = epi->ffd.file;
+       struct file *file = epi_fget(epi);
        __poll_t res;
 
+       /*
+        * We could return EPOLLERR | EPOLLHUP or something, but let's
+        * treat this more as "file doesn't exist, poll didn't happen".
+        */
+       if (!file)
+               return 0;
+
        pt->_key = epi->event.events;
        if (!is_file_epoll(file))
                res = vfs_poll(file, pt);
        else
                res = __ep_eventpoll_poll(file, pt, depth);
+       fput(file);
        return res & epi->event.events;
 }
 
index b6cad106c37e44258bd6e4433cd4aaedfbb98f65..0b2da7b7e2ad019ebf363ba652480476f702a75d 100644 (file)
@@ -310,6 +310,10 @@ struct cuse_init_args {
 /**
  * cuse_process_init_reply - finish initializing CUSE channel
  *
+ * @fm: The fuse mount information containing the CUSE connection.
+ * @args: The arguments passed to the init reply.
+ * @error: The error code signifying if any error occurred during the process.
+ *
  * This function creates the character device and sets up all the
  * required data structures for it.  Please read the comment at the
  * top of this file for high level overview.
index 4a6df591add61cd8960caa213e2102643bd2c8db..2b0d4781f39484d50d1fd7f4f673d8b08c5fd7cf 100644 (file)
@@ -1321,6 +1321,7 @@ retry:
                        err = fuse_do_statx(inode, file, stat);
                        if (err == -ENOSYS) {
                                fc->no_statx = 1;
+                               err = 0;
                                goto retry;
                        }
                } else {
index a56e7bffd0004e3755d648ad9b35f67d4eba863a..b57ce41576407be3d910da8916629f640668ee9a 100644 (file)
@@ -1362,7 +1362,7 @@ static void fuse_dio_lock(struct kiocb *iocb, struct iov_iter *from,
                          bool *exclusive)
 {
        struct inode *inode = file_inode(iocb->ki_filp);
-       struct fuse_file *ff = iocb->ki_filp->private_data;
+       struct fuse_inode *fi = get_fuse_inode(inode);
 
        *exclusive = fuse_dio_wr_exclusive_lock(iocb, from);
        if (*exclusive) {
@@ -1377,7 +1377,7 @@ static void fuse_dio_lock(struct kiocb *iocb, struct iov_iter *from,
                 * have raced, so check it again.
                 */
                if (fuse_io_past_eof(iocb, from) ||
-                   fuse_file_uncached_io_start(inode, ff, NULL) != 0) {
+                   fuse_inode_uncached_io_start(fi, NULL) != 0) {
                        inode_unlock_shared(inode);
                        inode_lock(inode);
                        *exclusive = true;
@@ -1388,13 +1388,13 @@ static void fuse_dio_lock(struct kiocb *iocb, struct iov_iter *from,
 static void fuse_dio_unlock(struct kiocb *iocb, bool exclusive)
 {
        struct inode *inode = file_inode(iocb->ki_filp);
-       struct fuse_file *ff = iocb->ki_filp->private_data;
+       struct fuse_inode *fi = get_fuse_inode(inode);
 
        if (exclusive) {
                inode_unlock(inode);
        } else {
                /* Allow opens in caching mode after last parallel dio end */
-               fuse_file_uncached_io_end(inode, ff);
+               fuse_inode_uncached_io_end(fi);
                inode_unlock_shared(inode);
        }
 }
@@ -2574,8 +2574,10 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
                 * First mmap of direct_io file enters caching inode io mode.
                 * Also waits for parallel dio writers to go into serial mode
                 * (exclusive instead of shared lock).
+                * After first mmap, the inode stays in caching io mode until
+                * the direct_io file release.
                 */
-               rc = fuse_file_cached_io_start(inode, ff);
+               rc = fuse_file_cached_io_open(inode, ff);
                if (rc)
                        return rc;
        }
index b24084b60864ee57c82864cffda5048dc7f45fb7..f2391961031374d8d55916c326c6472f0c03aae6 100644 (file)
@@ -1394,9 +1394,10 @@ int fuse_fileattr_set(struct mnt_idmap *idmap,
                      struct dentry *dentry, struct fileattr *fa);
 
 /* iomode.c */
-int fuse_file_cached_io_start(struct inode *inode, struct fuse_file *ff);
-int fuse_file_uncached_io_start(struct inode *inode, struct fuse_file *ff, struct fuse_backing *fb);
-void fuse_file_uncached_io_end(struct inode *inode, struct fuse_file *ff);
+int fuse_file_cached_io_open(struct inode *inode, struct fuse_file *ff);
+int fuse_inode_uncached_io_start(struct fuse_inode *fi,
+                                struct fuse_backing *fb);
+void fuse_inode_uncached_io_end(struct fuse_inode *fi);
 
 int fuse_file_io_open(struct file *file, struct inode *inode);
 void fuse_file_io_release(struct fuse_file *ff, struct inode *inode);
index 3a5d888783353cce48e18243ea386e97c788e12a..99e44ea7d8756ded7145f38b49d129b361b991ba 100644 (file)
@@ -175,6 +175,7 @@ static void fuse_evict_inode(struct inode *inode)
                }
        }
        if (S_ISREG(inode->i_mode) && !fuse_is_bad(inode)) {
+               WARN_ON(fi->iocachectr != 0);
                WARN_ON(!list_empty(&fi->write_files));
                WARN_ON(!list_empty(&fi->queued_writes));
        }
index c653ddcf057872663237a0be1820257a656d4945..c99e285f3183ef92f7662ac84956ad1a03315ea9 100644 (file)
@@ -21,12 +21,13 @@ static inline bool fuse_is_io_cache_wait(struct fuse_inode *fi)
 }
 
 /*
- * Start cached io mode.
+ * Called on cached file open() and on first mmap() of direct_io file.
+ * Takes cached_io inode mode reference to be dropped on file release.
  *
  * Blocks new parallel dio writes and waits for the in-progress parallel dio
  * writes to complete.
  */
-int fuse_file_cached_io_start(struct inode *inode, struct fuse_file *ff)
+int fuse_file_cached_io_open(struct inode *inode, struct fuse_file *ff)
 {
        struct fuse_inode *fi = get_fuse_inode(inode);
 
@@ -67,10 +68,9 @@ int fuse_file_cached_io_start(struct inode *inode, struct fuse_file *ff)
        return 0;
 }
 
-static void fuse_file_cached_io_end(struct inode *inode, struct fuse_file *ff)
+static void fuse_file_cached_io_release(struct fuse_file *ff,
+                                       struct fuse_inode *fi)
 {
-       struct fuse_inode *fi = get_fuse_inode(inode);
-
        spin_lock(&fi->lock);
        WARN_ON(fi->iocachectr <= 0);
        WARN_ON(ff->iomode != IOM_CACHED);
@@ -82,16 +82,15 @@ static void fuse_file_cached_io_end(struct inode *inode, struct fuse_file *ff)
 }
 
 /* Start strictly uncached io mode where cache access is not allowed */
-int fuse_file_uncached_io_start(struct inode *inode, struct fuse_file *ff, struct fuse_backing *fb)
+int fuse_inode_uncached_io_start(struct fuse_inode *fi, struct fuse_backing *fb)
 {
-       struct fuse_inode *fi = get_fuse_inode(inode);
        struct fuse_backing *oldfb;
        int err = 0;
 
        spin_lock(&fi->lock);
        /* deny conflicting backing files on same fuse inode */
        oldfb = fuse_inode_backing(fi);
-       if (oldfb && oldfb != fb) {
+       if (fb && oldfb && oldfb != fb) {
                err = -EBUSY;
                goto unlock;
        }
@@ -99,12 +98,10 @@ int fuse_file_uncached_io_start(struct inode *inode, struct fuse_file *ff, struc
                err = -ETXTBSY;
                goto unlock;
        }
-       WARN_ON(ff->iomode != IOM_NONE);
        fi->iocachectr--;
-       ff->iomode = IOM_UNCACHED;
 
        /* fuse inode holds a single refcount of backing file */
-       if (!oldfb) {
+       if (fb && !oldfb) {
                oldfb = fuse_inode_backing_set(fi, fb);
                WARN_ON_ONCE(oldfb != NULL);
        } else {
@@ -115,15 +112,29 @@ unlock:
        return err;
 }
 
-void fuse_file_uncached_io_end(struct inode *inode, struct fuse_file *ff)
+/* Takes uncached_io inode mode reference to be dropped on file release */
+static int fuse_file_uncached_io_open(struct inode *inode,
+                                     struct fuse_file *ff,
+                                     struct fuse_backing *fb)
 {
        struct fuse_inode *fi = get_fuse_inode(inode);
+       int err;
+
+       err = fuse_inode_uncached_io_start(fi, fb);
+       if (err)
+               return err;
+
+       WARN_ON(ff->iomode != IOM_NONE);
+       ff->iomode = IOM_UNCACHED;
+       return 0;
+}
+
+void fuse_inode_uncached_io_end(struct fuse_inode *fi)
+{
        struct fuse_backing *oldfb = NULL;
 
        spin_lock(&fi->lock);
        WARN_ON(fi->iocachectr >= 0);
-       WARN_ON(ff->iomode != IOM_UNCACHED);
-       ff->iomode = IOM_NONE;
        fi->iocachectr++;
        if (!fi->iocachectr) {
                wake_up(&fi->direct_io_waitq);
@@ -134,6 +145,15 @@ void fuse_file_uncached_io_end(struct inode *inode, struct fuse_file *ff)
                fuse_backing_put(oldfb);
 }
 
+/* Drop uncached_io reference from passthrough open */
+static void fuse_file_uncached_io_release(struct fuse_file *ff,
+                                         struct fuse_inode *fi)
+{
+       WARN_ON(ff->iomode != IOM_UNCACHED);
+       ff->iomode = IOM_NONE;
+       fuse_inode_uncached_io_end(fi);
+}
+
 /*
  * Open flags that are allowed in combination with FOPEN_PASSTHROUGH.
  * A combination of FOPEN_PASSTHROUGH and FOPEN_DIRECT_IO means that read/write
@@ -163,7 +183,7 @@ static int fuse_file_passthrough_open(struct inode *inode, struct file *file)
                return PTR_ERR(fb);
 
        /* First passthrough file open denies caching inode io mode */
-       err = fuse_file_uncached_io_start(inode, ff, fb);
+       err = fuse_file_uncached_io_open(inode, ff, fb);
        if (!err)
                return 0;
 
@@ -216,7 +236,7 @@ int fuse_file_io_open(struct file *file, struct inode *inode)
        if (ff->open_flags & FOPEN_PASSTHROUGH)
                err = fuse_file_passthrough_open(inode, file);
        else
-               err = fuse_file_cached_io_start(inode, ff);
+               err = fuse_file_cached_io_open(inode, ff);
        if (err)
                goto fail;
 
@@ -236,8 +256,10 @@ fail:
 /* No more pending io and no new io possible to inode via open/mmapped file */
 void fuse_file_io_release(struct fuse_file *ff, struct inode *inode)
 {
+       struct fuse_inode *fi = get_fuse_inode(inode);
+
        /*
-        * Last parallel dio close allows caching inode io mode.
+        * Last passthrough file close allows caching inode io mode.
         * Last caching file close exits caching inode io mode.
         */
        switch (ff->iomode) {
@@ -245,10 +267,10 @@ void fuse_file_io_release(struct fuse_file *ff, struct inode *inode)
                /* Nothing to do */
                break;
        case IOM_UNCACHED:
-               fuse_file_uncached_io_end(inode, ff);
+               fuse_file_uncached_io_release(ff, fi);
                break;
        case IOM_CACHED:
-               fuse_file_cached_io_end(inode, ff);
+               fuse_file_cached_io_release(ff, fi);
                break;
        }
 }
index 1d5abfdf0f22a626560b9ae6bb95309f8c146be5..fb0628e680c40f16fbee3b1b38b8bfcd70d1c980 100644 (file)
@@ -769,7 +769,7 @@ static int ioctl_getfsuuid(struct file *file, void __user *argp)
        struct fsuuid2 u = { .len = sb->s_uuid_len, };
 
        if (!sb->s_uuid_len)
-               return -ENOIOCTLCMD;
+               return -ENOTTY;
 
        memcpy(&u.uuid[0], &sb->s_uuid, sb->s_uuid_len);
 
@@ -781,7 +781,7 @@ static int ioctl_get_fs_sysfs_path(struct file *file, void __user *argp)
        struct super_block *sb = file_inode(file)->i_sb;
 
        if (!strlen(sb->s_sysfs_name))
-               return -ENOIOCTLCMD;
+               return -ENOTTY;
 
        struct fs_sysfs_path u = {};
 
index 9a0d32e4b422ad09518a6c6143638d0c68fb8b84..267b622d923b1fc63507300831c3163ba38d8a19 100644 (file)
@@ -164,7 +164,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
        enum netfs_how_to_modify howto;
        enum netfs_folio_trace trace;
        unsigned int bdp_flags = (iocb->ki_flags & IOCB_SYNC) ? 0: BDP_ASYNC;
-       ssize_t written = 0, ret;
+       ssize_t written = 0, ret, ret2;
        loff_t i_size, pos = iocb->ki_pos, from, to;
        size_t max_chunk = PAGE_SIZE << MAX_PAGECACHE_ORDER;
        bool maybe_trouble = false;
@@ -172,15 +172,14 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
        if (unlikely(test_bit(NETFS_ICTX_WRITETHROUGH, &ctx->flags) ||
                     iocb->ki_flags & (IOCB_DSYNC | IOCB_SYNC))
            ) {
-               if (pos < i_size_read(inode)) {
-                       ret = filemap_write_and_wait_range(mapping, pos, pos + iter->count);
-                       if (ret < 0) {
-                               goto out;
-                       }
-               }
-
                wbc_attach_fdatawrite_inode(&wbc, mapping->host);
 
+               ret = filemap_write_and_wait_range(mapping, pos, pos + iter->count);
+               if (ret < 0) {
+                       wbc_detach_inode(&wbc);
+                       goto out;
+               }
+
                wreq = netfs_begin_writethrough(iocb, iter->count);
                if (IS_ERR(wreq)) {
                        wbc_detach_inode(&wbc);
@@ -395,10 +394,12 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
 
 out:
        if (unlikely(wreq)) {
-               ret = netfs_end_writethrough(wreq, iocb);
+               ret2 = netfs_end_writethrough(wreq, iocb);
                wbc_detach_inode(&wbc);
-               if (ret == -EIOCBQUEUED)
-                       return ret;
+               if (ret2 == -EIOCBQUEUED)
+                       return ret2;
+               if (ret == 0)
+                       ret = ret2;
        }
 
        iocb->ki_pos += written;
index c709c296ea9a49e0ccecdae975a5287aea5759fe..acef52ecb1bb7ee01ff448f0c066d4bc1c9df932 100644 (file)
@@ -2429,7 +2429,12 @@ static int nfs_net_init(struct net *net)
        struct nfs_net *nn = net_generic(net, nfs_net_id);
 
        nfs_clients_init(net);
-       rpc_proc_register(net, &nn->rpcstats);
+
+       if (!rpc_proc_register(net, &nn->rpcstats)) {
+               nfs_clients_exit(net);
+               return -ENOMEM;
+       }
+
        return nfs_fs_proc_net_init(net);
 }
 
index 87c9547989f69ec8cb38b73da6868f52a84ff673..e88aca0c6e8ef17a613800f0a321a4c403d9e8e2 100644 (file)
@@ -983,15 +983,7 @@ static struct workqueue_struct *callback_wq;
 static bool nfsd4_queue_cb(struct nfsd4_callback *cb)
 {
        trace_nfsd_cb_queue(cb->cb_clp, cb);
-       return queue_delayed_work(callback_wq, &cb->cb_work, 0);
-}
-
-static void nfsd4_queue_cb_delayed(struct nfsd4_callback *cb,
-                                  unsigned long msecs)
-{
-       trace_nfsd_cb_queue(cb->cb_clp, cb);
-       queue_delayed_work(callback_wq, &cb->cb_work,
-                          msecs_to_jiffies(msecs));
+       return queue_work(callback_wq, &cb->cb_work);
 }
 
 static void nfsd41_cb_inflight_begin(struct nfs4_client *clp)
@@ -1490,7 +1482,7 @@ static void
 nfsd4_run_cb_work(struct work_struct *work)
 {
        struct nfsd4_callback *cb =
-               container_of(work, struct nfsd4_callback, cb_work.work);
+               container_of(work, struct nfsd4_callback, cb_work);
        struct nfs4_client *clp = cb->cb_clp;
        struct rpc_clnt *clnt;
        int flags;
@@ -1502,16 +1494,8 @@ nfsd4_run_cb_work(struct work_struct *work)
 
        clnt = clp->cl_cb_client;
        if (!clnt) {
-               if (test_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags))
-                       nfsd41_destroy_cb(cb);
-               else {
-                       /*
-                        * XXX: Ideally, we could wait for the client to
-                        *      reconnect, but I haven't figured out how
-                        *      to do that yet.
-                        */
-                       nfsd4_queue_cb_delayed(cb, 25);
-               }
+               /* Callback channel broken, or client killed; give up: */
+               nfsd41_destroy_cb(cb);
                return;
        }
 
@@ -1544,7 +1528,7 @@ void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp,
        cb->cb_msg.rpc_argp = cb;
        cb->cb_msg.rpc_resp = cb;
        cb->cb_ops = ops;
-       INIT_DELAYED_WORK(&cb->cb_work, nfsd4_run_cb_work);
+       INIT_WORK(&cb->cb_work, nfsd4_run_cb_work);
        cb->cb_status = 0;
        cb->cb_need_restart = false;
        cb->cb_holds_slot = false;
index fac938f563ad022ce79cdc5f67321bc7f529cc1c..a644460f3a5e7a7e3f8574ab922fef1e94ccb753 100644 (file)
@@ -3490,11 +3490,13 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
                    struct dentry *dentry, const u32 *bmval,
                    int ignore_crossmnt)
 {
+       DECLARE_BITMAP(attr_bitmap, ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops));
        struct nfsd4_fattr_args args;
        struct svc_fh *tempfh = NULL;
        int starting_len = xdr->buf->len;
        __be32 *attrlen_p, status;
        int attrlen_offset;
+       u32 attrmask[3];
        int err;
        struct nfsd4_compoundres *resp = rqstp->rq_resp;
        u32 minorversion = resp->cstate.minorversion;
@@ -3502,10 +3504,6 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
                .mnt    = exp->ex_path.mnt,
                .dentry = dentry,
        };
-       union {
-               u32             attrmask[3];
-               unsigned long   mask[2];
-       } u;
        unsigned long bit;
        bool file_modified = false;
        u64 size = 0;
@@ -3517,24 +3515,24 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
        args.exp = exp;
        args.dentry = dentry;
        args.ignore_crossmnt = (ignore_crossmnt != 0);
+       args.acl = NULL;
 
        /*
         * Make a local copy of the attribute bitmap that can be modified.
         */
-       memset(&u, 0, sizeof(u));
-       u.attrmask[0] = bmval[0];
-       u.attrmask[1] = bmval[1];
-       u.attrmask[2] = bmval[2];
+       attrmask[0] = bmval[0];
+       attrmask[1] = bmval[1];
+       attrmask[2] = bmval[2];
 
        args.rdattr_err = 0;
        if (exp->ex_fslocs.migrated) {
-               status = fattr_handle_absent_fs(&u.attrmask[0], &u.attrmask[1],
-                                               &u.attrmask[2], &args.rdattr_err);
+               status = fattr_handle_absent_fs(&attrmask[0], &attrmask[1],
+                                               &attrmask[2], &args.rdattr_err);
                if (status)
                        goto out;
        }
        args.size = 0;
-       if (u.attrmask[0] & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) {
+       if (attrmask[0] & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) {
                status = nfsd4_deleg_getattr_conflict(rqstp, d_inode(dentry),
                                        &file_modified, &size);
                if (status)
@@ -3553,16 +3551,16 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 
        if (!(args.stat.result_mask & STATX_BTIME))
                /* underlying FS does not offer btime so we can't share it */
-               u.attrmask[1] &= ~FATTR4_WORD1_TIME_CREATE;
-       if ((u.attrmask[0] & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE |
+               attrmask[1] &= ~FATTR4_WORD1_TIME_CREATE;
+       if ((attrmask[0] & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE |
                        FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_MAXNAME)) ||
-           (u.attrmask[1] & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
+           (attrmask[1] & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
                       FATTR4_WORD1_SPACE_TOTAL))) {
                err = vfs_statfs(&path, &args.statfs);
                if (err)
                        goto out_nfserr;
        }
-       if ((u.attrmask[0] & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) &&
+       if ((attrmask[0] & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) &&
            !fhp) {
                tempfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
                status = nfserr_jukebox;
@@ -3576,11 +3574,10 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
        } else
                args.fhp = fhp;
 
-       args.acl = NULL;
-       if (u.attrmask[0] & FATTR4_WORD0_ACL) {
+       if (attrmask[0] & FATTR4_WORD0_ACL) {
                err = nfsd4_get_nfs4_acl(rqstp, dentry, &args.acl);
                if (err == -EOPNOTSUPP)
-                       u.attrmask[0] &= ~FATTR4_WORD0_ACL;
+                       attrmask[0] &= ~FATTR4_WORD0_ACL;
                else if (err == -EINVAL) {
                        status = nfserr_attrnotsupp;
                        goto out;
@@ -3592,17 +3589,17 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 
 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
        args.context = NULL;
-       if ((u.attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) ||
-            u.attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
+       if ((attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) ||
+            attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
                if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
                        err = security_inode_getsecctx(d_inode(dentry),
                                                &args.context, &args.contextlen);
                else
                        err = -EOPNOTSUPP;
                args.contextsupport = (err == 0);
-               if (u.attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) {
+               if (attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) {
                        if (err == -EOPNOTSUPP)
-                               u.attrmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
+                               attrmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
                        else if (err)
                                goto out_nfserr;
                }
@@ -3610,8 +3607,8 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
 
        /* attrmask */
-       status = nfsd4_encode_bitmap4(xdr, u.attrmask[0],
-                                     u.attrmask[1], u.attrmask[2]);
+       status = nfsd4_encode_bitmap4(xdr, attrmask[0], attrmask[1],
+                                     attrmask[2]);
        if (status)
                goto out;
 
@@ -3620,7 +3617,9 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
        attrlen_p = xdr_reserve_space(xdr, XDR_UNIT);
        if (!attrlen_p)
                goto out_resource;
-       for_each_set_bit(bit, (const unsigned long *)&u.mask,
+       bitmap_from_arr32(attr_bitmap, attrmask,
+                         ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops));
+       for_each_set_bit(bit, attr_bitmap,
                         ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops)) {
                status = nfsd4_enc_fattr4_encode_ops[bit](xdr, &args);
                if (status != nfs_ok)
index 01c6f344564693dd0987413c0ed116458782a677..2ed0fcf879fd17be57d1d963ad74e864d73315f5 100644 (file)
@@ -68,7 +68,7 @@ struct nfsd4_callback {
        struct nfs4_client *cb_clp;
        struct rpc_message cb_msg;
        const struct nfsd4_callback_ops *cb_ops;
-       struct delayed_work cb_work;
+       struct work_struct cb_work;
        int cb_seq_status;
        int cb_status;
        bool cb_need_restart;
index bc846b904b68d43816c48c69c3ae83152cadabf1..aee40db7a036fb9f7d34e2e456fb6d61ae3bbf2d 100644 (file)
@@ -240,7 +240,7 @@ nilfs_filetype_table[NILFS_FT_MAX] = {
 
 #define S_SHIFT 12
 static unsigned char
-nilfs_type_by_mode[S_IFMT >> S_SHIFT] = {
+nilfs_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = {
        [S_IFREG >> S_SHIFT]    = NILFS_FT_REG_FILE,
        [S_IFDIR >> S_SHIFT]    = NILFS_FT_DIR,
        [S_IFCHR >> S_SHIFT]    = NILFS_FT_CHRDEV,
index cdfdf51e55d797e0e5fecc349e2f157f09fea7d8..7bc31d69f680dd996f8503c9d06f0a0b96522e80 100644 (file)
@@ -46,3 +46,12 @@ config NTFS3_FS_POSIX_ACL
          NOTE: this is linux only feature. Windows will ignore these ACLs.
 
          If you don't know what Access Control Lists are, say N.
+
+config NTFS_FS
+       tristate "NTFS file system support"
+       select NTFS3_FS
+       select BUFFER_HEAD
+       select NLS
+       help
+         This config option is here only for backward compatibility. NTFS
+         filesystem is now handled by the NTFS3 driver.
index 5cf3d9decf646b1935517e8b564d807626e60e0f..263635199b60d38a23b98c10f31d2105d832eda4 100644 (file)
@@ -616,4 +616,11 @@ const struct file_operations ntfs_dir_operations = {
        .compat_ioctl   = ntfs_compat_ioctl,
 #endif
 };
+
+const struct file_operations ntfs_legacy_dir_operations = {
+       .llseek         = generic_file_llseek,
+       .read           = generic_read_dir,
+       .iterate_shared = ntfs_readdir,
+       .open           = ntfs_file_open,
+};
 // clang-format on
index 5418662c80d8878afe72a8b8e8ffc43cc834b176..b73969e05052ae8bcd49740057405e3e71c0852a 100644 (file)
@@ -1236,4 +1236,12 @@ const struct file_operations ntfs_file_operations = {
        .fallocate      = ntfs_fallocate,
        .release        = ntfs_file_release,
 };
+
+const struct file_operations ntfs_legacy_file_operations = {
+       .llseek         = generic_file_llseek,
+       .read_iter      = ntfs_file_read_iter,
+       .splice_read    = ntfs_file_splice_read,
+       .open           = ntfs_file_open,
+       .release        = ntfs_file_release,
+};
 // clang-format on
index eb7a8c9fba0183f40096d673473be4dffaa7c4c8..d273eda1cf45d68e90cc56866fe689a629be43b5 100644 (file)
@@ -440,7 +440,10 @@ end_enum:
                 * Usually a hard links to directories are disabled.
                 */
                inode->i_op = &ntfs_dir_inode_operations;
-               inode->i_fop = &ntfs_dir_operations;
+               if (is_legacy_ntfs(inode->i_sb))
+                       inode->i_fop = &ntfs_legacy_dir_operations;
+               else
+                       inode->i_fop = &ntfs_dir_operations;
                ni->i_valid = 0;
        } else if (S_ISLNK(mode)) {
                ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY;
@@ -450,7 +453,10 @@ end_enum:
        } else if (S_ISREG(mode)) {
                ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY;
                inode->i_op = &ntfs_file_inode_operations;
-               inode->i_fop = &ntfs_file_operations;
+               if (is_legacy_ntfs(inode->i_sb))
+                       inode->i_fop = &ntfs_legacy_file_operations;
+               else
+                       inode->i_fop = &ntfs_file_operations;
                inode->i_mapping->a_ops = is_compressed(ni) ? &ntfs_aops_cmpr :
                                                              &ntfs_aops;
                if (ino != MFT_REC_MFT)
@@ -1614,7 +1620,10 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
 
        if (S_ISDIR(mode)) {
                inode->i_op = &ntfs_dir_inode_operations;
-               inode->i_fop = &ntfs_dir_operations;
+               if (is_legacy_ntfs(inode->i_sb))
+                       inode->i_fop = &ntfs_legacy_dir_operations;
+               else
+                       inode->i_fop = &ntfs_dir_operations;
        } else if (S_ISLNK(mode)) {
                inode->i_op = &ntfs_link_inode_operations;
                inode->i_fop = NULL;
@@ -1623,7 +1632,10 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
                inode_nohighmem(inode);
        } else if (S_ISREG(mode)) {
                inode->i_op = &ntfs_file_inode_operations;
-               inode->i_fop = &ntfs_file_operations;
+               if (is_legacy_ntfs(inode->i_sb))
+                       inode->i_fop = &ntfs_legacy_file_operations;
+               else
+                       inode->i_fop = &ntfs_file_operations;
                inode->i_mapping->a_ops = is_compressed(ni) ? &ntfs_aops_cmpr :
                                                              &ntfs_aops;
                init_rwsem(&ni->file.run_lock);
index 79356fd29a14141de34ed006517b153fd9e4872b..5f4d288c6adfb955fb21bc513cae69f80cb61b20 100644 (file)
@@ -493,6 +493,7 @@ struct inode *dir_search_u(struct inode *dir, const struct cpu_str *uni,
                           struct ntfs_fnd *fnd);
 bool dir_is_empty(struct inode *dir);
 extern const struct file_operations ntfs_dir_operations;
+extern const struct file_operations ntfs_legacy_dir_operations;
 
 /* Globals from file.c */
 int ntfs_getattr(struct mnt_idmap *idmap, const struct path *path,
@@ -507,6 +508,7 @@ long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg);
 extern const struct inode_operations ntfs_special_inode_operations;
 extern const struct inode_operations ntfs_file_inode_operations;
 extern const struct file_operations ntfs_file_operations;
+extern const struct file_operations ntfs_legacy_file_operations;
 
 /* Globals from frecord.c */
 void ni_remove_mi(struct ntfs_inode *ni, struct mft_inode *mi);
@@ -1154,4 +1156,6 @@ static inline void le64_sub_cpu(__le64 *var, u64 val)
        *var = cpu_to_le64(le64_to_cpu(*var) - val);
 }
 
+bool is_legacy_ntfs(struct super_block *sb);
+
 #endif /* _LINUX_NTFS3_NTFS_FS_H */
index 9df7c20d066f6125dda2406a0481e4eab300bb80..b26d95a8d3274d061fc2f0dc2ba7f19cd385db8a 100644 (file)
@@ -408,6 +408,12 @@ static int ntfs_fs_reconfigure(struct fs_context *fc)
        struct ntfs_mount_options *new_opts = fc->fs_private;
        int ro_rw;
 
+       /* If ntfs3 is used as legacy ntfs enforce read-only mode. */
+       if (is_legacy_ntfs(sb)) {
+               fc->sb_flags |= SB_RDONLY;
+               goto out;
+       }
+
        ro_rw = sb_rdonly(sb) && !(fc->sb_flags & SB_RDONLY);
        if (ro_rw && (sbi->flags & NTFS_FLAGS_NEED_REPLAY)) {
                errorf(fc,
@@ -427,8 +433,6 @@ static int ntfs_fs_reconfigure(struct fs_context *fc)
                        fc,
                        "ntfs3: Cannot use different iocharset when remounting!");
 
-       sync_filesystem(sb);
-
        if (ro_rw && (sbi->volume.flags & VOLUME_FLAG_DIRTY) &&
            !new_opts->force) {
                errorf(fc,
@@ -436,6 +440,8 @@ static int ntfs_fs_reconfigure(struct fs_context *fc)
                return -EINVAL;
        }
 
+out:
+       sync_filesystem(sb);
        swap(sbi->options, fc->fs_private);
 
        return 0;
@@ -1613,6 +1619,8 @@ load_root:
        }
 #endif
 
+       if (is_legacy_ntfs(sb))
+               sb->s_flags |= SB_RDONLY;
        return 0;
 
 put_inode_out:
@@ -1730,7 +1738,7 @@ static const struct fs_context_operations ntfs_context_ops = {
  * This will called when mount/remount. We will first initialize
  * options so that if remount we can use just that.
  */
-static int ntfs_init_fs_context(struct fs_context *fc)
+static int __ntfs_init_fs_context(struct fs_context *fc)
 {
        struct ntfs_mount_options *opts;
        struct ntfs_sb_info *sbi;
@@ -1778,6 +1786,11 @@ free_opts:
        return -ENOMEM;
 }
 
+static int ntfs_init_fs_context(struct fs_context *fc)
+{
+       return __ntfs_init_fs_context(fc);
+}
+
 static void ntfs3_kill_sb(struct super_block *sb)
 {
        struct ntfs_sb_info *sbi = sb->s_fs_info;
@@ -1798,6 +1811,50 @@ static struct file_system_type ntfs_fs_type = {
        .kill_sb                = ntfs3_kill_sb,
        .fs_flags               = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
 };
+
+#if IS_ENABLED(CONFIG_NTFS_FS)
+static int ntfs_legacy_init_fs_context(struct fs_context *fc)
+{
+       int ret;
+
+       ret = __ntfs_init_fs_context(fc);
+       /* If ntfs3 is used as legacy ntfs enforce read-only mode. */
+       fc->sb_flags |= SB_RDONLY;
+       return ret;
+}
+
+static struct file_system_type ntfs_legacy_fs_type = {
+       .owner                  = THIS_MODULE,
+       .name                   = "ntfs",
+       .init_fs_context        = ntfs_legacy_init_fs_context,
+       .parameters             = ntfs_fs_parameters,
+       .kill_sb                = ntfs3_kill_sb,
+       .fs_flags               = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
+};
+MODULE_ALIAS_FS("ntfs");
+
+static inline void register_as_ntfs_legacy(void)
+{
+       int err = register_filesystem(&ntfs_legacy_fs_type);
+       if (err)
+               pr_warn("ntfs3: Failed to register legacy ntfs filesystem driver: %d\n", err);
+}
+
+static inline void unregister_as_ntfs_legacy(void)
+{
+       unregister_filesystem(&ntfs_legacy_fs_type);
+}
+bool is_legacy_ntfs(struct super_block *sb)
+{
+       return sb->s_type == &ntfs_legacy_fs_type;
+}
+#else
+static inline void register_as_ntfs_legacy(void) {}
+static inline void unregister_as_ntfs_legacy(void) {}
+bool is_legacy_ntfs(struct super_block *sb) { return false; }
+#endif
+
+
 // clang-format on
 
 static int __init init_ntfs_fs(void)
@@ -1832,6 +1889,7 @@ static int __init init_ntfs_fs(void)
                goto out1;
        }
 
+       register_as_ntfs_legacy();
        err = register_filesystem(&ntfs_fs_type);
        if (err)
                goto out;
@@ -1849,6 +1907,7 @@ static void __exit exit_ntfs_fs(void)
        rcu_barrier();
        kmem_cache_destroy(ntfs_inode_cachep);
        unregister_filesystem(&ntfs_fs_type);
+       unregister_as_ntfs_legacy();
        ntfs3_exit_bitmap();
 
 #ifdef CONFIG_PROC_FS
index 195b077c0facbf8159b706361172c91a74c8815c..9223856c934b40e66132f99fcccf937cb14cbe6a 100644 (file)
@@ -67,7 +67,7 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf,
                 */
                ppage = pfn_to_online_page(pfn);
 
-               if (!ppage || PageSlab(ppage) || page_has_type(ppage))
+               if (!ppage)
                        pcount = 0;
                else
                        pcount = page_mapcount(ppage);
@@ -124,11 +124,8 @@ u64 stable_page_flags(struct page *page)
 
        /*
         * pseudo flags for the well known (anonymous) memory mapped pages
-        *
-        * Note that page->_mapcount is overloaded in SLAB, so the
-        * simple test in page_mapped() is not enough.
         */
-       if (!PageSlab(page) && page_mapped(page))
+       if (page_mapped(page))
                u |= 1 << KPF_MMAP;
        if (PageAnon(page))
                u |= 1 << KPF_ANON;
index d41eedbff674abb0e62e52ae6cc585aaa5d83d77..39277c37185cac3327c0f002849b1f5fc621cd05 100644 (file)
@@ -389,6 +389,7 @@ cifs_alloc_inode(struct super_block *sb)
         * server, can not assume caching of file data or metadata.
         */
        cifs_set_oplock_level(cifs_inode, 0);
+       cifs_inode->lease_granted = false;
        cifs_inode->flags = 0;
        spin_lock_init(&cifs_inode->writers_lock);
        cifs_inode->writers = 0;
@@ -739,6 +740,8 @@ static void cifs_umount_begin(struct super_block *sb)
 
        spin_lock(&cifs_tcp_ses_lock);
        spin_lock(&tcon->tc_lock);
+       trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                           netfs_trace_tcon_ref_see_umount);
        if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) {
                /* we have other mounts to same share or we have
                   already tried to umount this and woken up
index d6669ce4ae87f07415b150eaffcbf429c4fe74bd..6ff35570db813a533ef9221fad6a7aea99e6d1d2 100644 (file)
@@ -1190,6 +1190,7 @@ struct cifs_fattr {
  */
 struct cifs_tcon {
        struct list_head tcon_list;
+       int debug_id;           /* Debugging for tracing */
        int tc_count;
        struct list_head rlist; /* reconnect list */
        spinlock_t tc_lock;  /* protect anything here that is not protected */
@@ -1276,7 +1277,9 @@ struct cifs_tcon {
        __u32 max_cached_dirs;
 #ifdef CONFIG_CIFS_FSCACHE
        u64 resource_id;                /* server resource id */
+       bool fscache_acquired;          /* T if we've tried acquiring a cookie */
        struct fscache_volume *fscache; /* cookie for share */
+       struct mutex fscache_lock;      /* Prevent regetting a cookie */
 #endif
        struct list_head pending_opens; /* list of incomplete opens */
        struct cached_fids *cfids;
index c0513fbb8a59d4dbafa0738c28038048c785a5ae..c46d418c1c0c3ea065eaa5d4f4f751750df90080 100644 (file)
@@ -882,7 +882,7 @@ typedef struct smb_com_open_rsp {
        __u8 OplockLevel;
        __u16 Fid;
        __le32 CreateAction;
-       struct_group(common_attributes,
+       struct_group_attr(common_attributes, __packed,
                __le64 CreationTime;
                __le64 LastAccessTime;
                __le64 LastWriteTime;
@@ -2266,7 +2266,7 @@ typedef struct {
 /* QueryFileInfo/QueryPathinfo (also for SetPath/SetFile) data buffer formats */
 /******************************************************************************/
 typedef struct { /* data block encoding of response to level 263 QPathInfo */
-       struct_group(common_attributes,
+       struct_group_attr(common_attributes, __packed,
                __le64 CreationTime;
                __le64 LastAccessTime;
                __le64 LastWriteTime;
index 8e0a348f1f660ebc14498c7fd7d342693411c106..fbc358c09da3b1d7ffc495d0c461e32509f95c1c 100644 (file)
@@ -303,7 +303,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
                     struct TCP_Server_Info *primary_server);
 extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
                                 int from_reconnect);
-extern void cifs_put_tcon(struct cifs_tcon *tcon);
+extern void cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace);
 
 extern void cifs_release_automount_timer(void);
 
@@ -530,8 +530,9 @@ extern int CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses);
 
 extern struct cifs_ses *sesInfoAlloc(void);
 extern void sesInfoFree(struct cifs_ses *);
-extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled);
-extern void tconInfoFree(struct cifs_tcon *);
+extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled,
+                                        enum smb3_tcon_ref_trace trace);
+extern void tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace);
 
 extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
                   __u32 *pexpected_response_sequence_number);
@@ -721,8 +722,6 @@ static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options)
                return options;
 }
 
-struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon);
-void cifs_put_tcon_super(struct super_block *sb);
 int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry);
 
 /* Put references of @ses and its children */
index 4e35970681bf052dc343c23935549600f5ce8859..7a16e12f5da879bbbb8ace98a4ec4f30aafec33e 100644 (file)
@@ -1943,7 +1943,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
        }
 
        /* no need to setup directory caching on IPC share, so pass in false */
-       tcon = tcon_info_alloc(false);
+       tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_ipc);
        if (tcon == NULL)
                return -ENOMEM;
 
@@ -1960,7 +1960,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
 
        if (rc) {
                cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
-               tconInfoFree(tcon);
+               tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc_fail);
                goto out;
        }
 
@@ -2043,7 +2043,7 @@ void __cifs_put_smb_ses(struct cifs_ses *ses)
         * files on session close, as specified in MS-SMB2 3.3.5.6 Receiving an
         * SMB2 LOGOFF Request.
         */
-       tconInfoFree(tcon);
+       tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc);
        if (do_logoff) {
                xid = get_xid();
                rc = server->ops->logoff(xid, ses);
@@ -2432,6 +2432,8 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
                        continue;
                }
                ++tcon->tc_count;
+               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                   netfs_trace_tcon_ref_get_find);
                spin_unlock(&tcon->tc_lock);
                spin_unlock(&cifs_tcp_ses_lock);
                return tcon;
@@ -2441,7 +2443,7 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
 }
 
 void
-cifs_put_tcon(struct cifs_tcon *tcon)
+cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
 {
        unsigned int xid;
        struct cifs_ses *ses;
@@ -2457,6 +2459,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
        cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
        spin_lock(&cifs_tcp_ses_lock);
        spin_lock(&tcon->tc_lock);
+       trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count - 1, trace);
        if (--tcon->tc_count > 0) {
                spin_unlock(&tcon->tc_lock);
                spin_unlock(&cifs_tcp_ses_lock);
@@ -2493,7 +2496,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
        _free_xid(xid);
 
        cifs_fscache_release_super_cookie(tcon);
-       tconInfoFree(tcon);
+       tconInfoFree(tcon, netfs_trace_tcon_ref_free);
        cifs_put_smb_ses(ses);
 }
 
@@ -2547,7 +2550,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
                nohandlecache = ctx->nohandlecache;
        else
                nohandlecache = true;
-       tcon = tcon_info_alloc(!nohandlecache);
+       tcon = tcon_info_alloc(!nohandlecache, netfs_trace_tcon_ref_new);
        if (tcon == NULL) {
                rc = -ENOMEM;
                goto out_fail;
@@ -2737,7 +2740,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
        return tcon;
 
 out_fail:
-       tconInfoFree(tcon);
+       tconInfoFree(tcon, netfs_trace_tcon_ref_free_fail);
        return ERR_PTR(rc);
 }
 
@@ -2754,7 +2757,7 @@ cifs_put_tlink(struct tcon_link *tlink)
        }
 
        if (!IS_ERR(tlink_tcon(tlink)))
-               cifs_put_tcon(tlink_tcon(tlink));
+               cifs_put_tcon(tlink_tcon(tlink), netfs_trace_tcon_ref_put_tlink);
        kfree(tlink);
 }
 
@@ -3319,7 +3322,7 @@ void cifs_mount_put_conns(struct cifs_mount_ctx *mnt_ctx)
        int rc = 0;
 
        if (mnt_ctx->tcon)
-               cifs_put_tcon(mnt_ctx->tcon);
+               cifs_put_tcon(mnt_ctx->tcon, netfs_trace_tcon_ref_put_mnt_ctx);
        else if (mnt_ctx->ses)
                cifs_put_smb_ses(mnt_ctx->ses);
        else if (mnt_ctx->server)
index 6c727d8c31e870ddd0f809db12b21aae76ac80cd..3bbac925d0766b8c456d731355e71b1594b94af3 100644 (file)
@@ -748,6 +748,16 @@ static int smb3_fs_context_validate(struct fs_context *fc)
        /* set the port that we got earlier */
        cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
 
+       if (ctx->uid_specified && !ctx->forceuid_specified) {
+               ctx->override_uid = 1;
+               pr_notice("enabling forceuid mount option implicitly because uid= option is specified\n");
+       }
+
+       if (ctx->gid_specified && !ctx->forcegid_specified) {
+               ctx->override_gid = 1;
+               pr_notice("enabling forcegid mount option implicitly because gid= option is specified\n");
+       }
+
        if (ctx->override_uid && !ctx->uid_specified) {
                ctx->override_uid = 0;
                pr_notice("ignoring forceuid mount option specified with no uid= option\n");
@@ -1019,12 +1029,14 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
                        ctx->override_uid = 0;
                else
                        ctx->override_uid = 1;
+               ctx->forceuid_specified = true;
                break;
        case Opt_forcegid:
                if (result.negated)
                        ctx->override_gid = 0;
                else
                        ctx->override_gid = 1;
+               ctx->forcegid_specified = true;
                break;
        case Opt_perm:
                if (result.negated)
index a947bddeba273ea850b3502f07555a19316266a6..cf577ec0dd0ac4a8f5a3131e8ed0c3ce9574a4d7 100644 (file)
@@ -165,6 +165,8 @@ enum cifs_param {
 };
 
 struct smb3_fs_context {
+       bool forceuid_specified;
+       bool forcegid_specified;
        bool uid_specified;
        bool cruid_specified;
        bool gid_specified;
index 340efce8f052951a308329b70b5846d9e57477f5..1a895e6243ee9aaf21fc8405893ce52ed14303a2 100644 (file)
@@ -43,12 +43,23 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
        char *key;
        int ret = -ENOMEM;
 
+       if (tcon->fscache_acquired)
+               return 0;
+
+       mutex_lock(&tcon->fscache_lock);
+       if (tcon->fscache_acquired) {
+               mutex_unlock(&tcon->fscache_lock);
+               return 0;
+       }
+       tcon->fscache_acquired = true;
+
        tcon->fscache = NULL;
        switch (sa->sa_family) {
        case AF_INET:
        case AF_INET6:
                break;
        default:
+               mutex_unlock(&tcon->fscache_lock);
                cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
                return -EINVAL;
        }
@@ -57,6 +68,7 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
 
        sharename = extract_sharename(tcon->tree_name);
        if (IS_ERR(sharename)) {
+               mutex_unlock(&tcon->fscache_lock);
                cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
                return PTR_ERR(sharename);
        }
@@ -82,6 +94,11 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
                }
                pr_err("Cache volume key already in use (%s)\n", key);
                vcookie = NULL;
+               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                   netfs_trace_tcon_ref_see_fscache_collision);
+       } else {
+               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                   netfs_trace_tcon_ref_see_fscache_okay);
        }
 
        tcon->fscache = vcookie;
@@ -90,6 +107,7 @@ out_2:
        kfree(key);
 out:
        kfree(sharename);
+       mutex_unlock(&tcon->fscache_lock);
        return ret;
 }
 
@@ -102,6 +120,8 @@ void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
        cifs_fscache_fill_volume_coherency(tcon, &cd);
        fscache_relinquish_volume(tcon->fscache, &cd, false);
        tcon->fscache = NULL;
+       trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                           netfs_trace_tcon_ref_see_fscache_relinq);
 }
 
 void cifs_fscache_get_inode_cookie(struct inode *inode)
index 7d15a1969b818439515b5188e8662a3b8f1276ce..07c468ddb88a89d65f8a48433a055759deb3da26 100644 (file)
@@ -111,9 +111,10 @@ sesInfoFree(struct cifs_ses *buf_to_free)
 }
 
 struct cifs_tcon *
-tcon_info_alloc(bool dir_leases_enabled)
+tcon_info_alloc(bool dir_leases_enabled, enum smb3_tcon_ref_trace trace)
 {
        struct cifs_tcon *ret_buf;
+       static atomic_t tcon_debug_id;
 
        ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL);
        if (!ret_buf)
@@ -130,7 +131,8 @@ tcon_info_alloc(bool dir_leases_enabled)
 
        atomic_inc(&tconInfoAllocCount);
        ret_buf->status = TID_NEW;
-       ++ret_buf->tc_count;
+       ret_buf->debug_id = atomic_inc_return(&tcon_debug_id);
+       ret_buf->tc_count = 1;
        spin_lock_init(&ret_buf->tc_lock);
        INIT_LIST_HEAD(&ret_buf->openFileList);
        INIT_LIST_HEAD(&ret_buf->tcon_list);
@@ -139,17 +141,22 @@ tcon_info_alloc(bool dir_leases_enabled)
        atomic_set(&ret_buf->num_local_opens, 0);
        atomic_set(&ret_buf->num_remote_opens, 0);
        ret_buf->stats_from_time = ktime_get_real_seconds();
+#ifdef CONFIG_CIFS_FSCACHE
+       mutex_init(&ret_buf->fscache_lock);
+#endif
+       trace_smb3_tcon_ref(ret_buf->debug_id, ret_buf->tc_count, trace);
 
        return ret_buf;
 }
 
 void
-tconInfoFree(struct cifs_tcon *tcon)
+tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
 {
        if (tcon == NULL) {
                cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n");
                return;
        }
+       trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, trace);
        free_cached_dirs(tcon->cfids);
        atomic_dec(&tconInfoAllocCount);
        kfree(tcon->nativeFileSystem);
index cc72be5a93a933b09c45256c2a7d7615478f54c0..677ef6f99a5be407fb9c73baba7918cf5e28244e 100644 (file)
@@ -767,7 +767,7 @@ smb2_cancelled_close_fid(struct work_struct *work)
        if (rc)
                cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d\n", rc);
 
-       cifs_put_tcon(tcon);
+       cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close_fid);
        kfree(cancelled);
 }
 
@@ -811,6 +811,8 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
        if (tcon->tc_count <= 0) {
                struct TCP_Server_Info *server = NULL;
 
+               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                   netfs_trace_tcon_ref_see_cancelled_close);
                WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative");
                spin_unlock(&cifs_tcp_ses_lock);
 
@@ -823,12 +825,14 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
                return 0;
        }
        tcon->tc_count++;
+       trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                           netfs_trace_tcon_ref_get_cancelled_close);
        spin_unlock(&cifs_tcp_ses_lock);
 
        rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0,
                                         persistent_fid, volatile_fid);
        if (rc)
-               cifs_put_tcon(tcon);
+               cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close);
 
        return rc;
 }
@@ -856,7 +860,7 @@ smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_Server_Info *serve
                                         rsp->PersistentFileId,
                                         rsp->VolatileFileId);
        if (rc)
-               cifs_put_tcon(tcon);
+               cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_mid);
 
        return rc;
 }
index 78c94d0350fe9970fab31564aeba6870d71859bd..28f0b7d19d534b18bff680bb739247889ac7675b 100644 (file)
@@ -2915,8 +2915,11 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
                tcon = list_first_entry_or_null(&ses->tcon_list,
                                                struct cifs_tcon,
                                                tcon_list);
-               if (tcon)
+               if (tcon) {
                        tcon->tc_count++;
+                       trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                           netfs_trace_tcon_ref_get_dfs_refer);
+               }
                spin_unlock(&cifs_tcp_ses_lock);
        }
 
@@ -2980,6 +2983,8 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
                /* ipc tcons are not refcounted */
                spin_lock(&cifs_tcp_ses_lock);
                tcon->tc_count--;
+               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                   netfs_trace_tcon_ref_dec_dfs_refer);
                /* tc_count can never go negative */
                WARN_ON(tcon->tc_count < 0);
                spin_unlock(&cifs_tcp_ses_lock);
index 86c647a947ccd1065a8edb0712e113351839b96f..a5efce03cb58e2d995862f8c3b0cc081f8beed5b 100644 (file)
@@ -4138,6 +4138,8 @@ void smb2_reconnect_server(struct work_struct *work)
                list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
                        if (tcon->need_reconnect || tcon->need_reopen_files) {
                                tcon->tc_count++;
+                               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                                   netfs_trace_tcon_ref_get_reconnect_server);
                                list_add_tail(&tcon->rlist, &tmp_list);
                                tcon_selected = true;
                        }
@@ -4176,14 +4178,14 @@ void smb2_reconnect_server(struct work_struct *work)
                if (tcon->ipc)
                        cifs_put_smb_ses(tcon->ses);
                else
-                       cifs_put_tcon(tcon);
+                       cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_reconnect_server);
        }
 
        if (!ses_exist)
                goto done;
 
        /* allocate a dummy tcon struct used for reconnect */
-       tcon = tcon_info_alloc(false);
+       tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_reconnect_server);
        if (!tcon) {
                resched = true;
                list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
@@ -4206,7 +4208,7 @@ void smb2_reconnect_server(struct work_struct *work)
                list_del_init(&ses->rlist);
                cifs_put_smb_ses(ses);
        }
-       tconInfoFree(tcon);
+       tconInfoFree(tcon, netfs_trace_tcon_ref_free_reconnect_server);
 
 done:
        cifs_dbg(FYI, "Reconnecting tcons and channels finished\n");
index c72a3b2886b7ff6333b19312198eba060d01507f..2fccf0d4f53d2743153f973b9c31c5c700e27170 100644 (file)
@@ -320,7 +320,7 @@ struct smb2_file_reparse_point_info {
 } __packed;
 
 struct smb2_file_network_open_info {
-       struct_group(network_open_info,
+       struct_group_attr(network_open_info, __packed,
                __le64 CreationTime;
                __le64 LastAccessTime;
                __le64 LastWriteTime;
index 1d6e54f7879e6a5e8034a90d30471fecc02d2d1b..02135a6053051ee6848f8df90be30fc2c805af6d 100644 (file)
@@ -189,6 +189,8 @@ smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32  tid)
                if (tcon->tid != tid)
                        continue;
                ++tcon->tc_count;
+               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                   netfs_trace_tcon_ref_get_find_sess_tcon);
                return tcon;
        }
 
index 5e83cb9da9028e0d15383e6e19413ea1da31e553..604e52876cd2d98e9a86941b0c527dbe6d8abe6a 100644 (file)
@@ -3,6 +3,9 @@
  *   Copyright (C) 2018, Microsoft Corporation.
  *
  *   Author(s): Steve French <stfrench@microsoft.com>
+ *
+ * Please use this 3-part article as a reference for writing new tracepoints:
+ * https://lwn.net/Articles/379903/
  */
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM cifs
 #include <linux/inet.h>
 
 /*
- * Please use this 3-part article as a reference for writing new tracepoints:
- * https://lwn.net/Articles/379903/
+ * Specify enums for tracing information.
+ */
+#define smb3_tcon_ref_traces                                         \
+       EM(netfs_trace_tcon_ref_dec_dfs_refer,          "DEC DfsRef") \
+       EM(netfs_trace_tcon_ref_free,                   "FRE       ") \
+       EM(netfs_trace_tcon_ref_free_fail,              "FRE Fail  ") \
+       EM(netfs_trace_tcon_ref_free_ipc,               "FRE Ipc   ") \
+       EM(netfs_trace_tcon_ref_free_ipc_fail,          "FRE Ipc-F ") \
+       EM(netfs_trace_tcon_ref_free_reconnect_server,  "FRE Reconn") \
+       EM(netfs_trace_tcon_ref_get_cancelled_close,    "GET Cn-Cls") \
+       EM(netfs_trace_tcon_ref_get_dfs_refer,          "GET DfsRef") \
+       EM(netfs_trace_tcon_ref_get_find,               "GET Find  ") \
+       EM(netfs_trace_tcon_ref_get_find_sess_tcon,     "GET FndSes") \
+       EM(netfs_trace_tcon_ref_get_reconnect_server,   "GET Reconn") \
+       EM(netfs_trace_tcon_ref_new,                    "NEW       ") \
+       EM(netfs_trace_tcon_ref_new_ipc,                "NEW Ipc   ") \
+       EM(netfs_trace_tcon_ref_new_reconnect_server,   "NEW Reconn") \
+       EM(netfs_trace_tcon_ref_put_cancelled_close,    "PUT Cn-Cls") \
+       EM(netfs_trace_tcon_ref_put_cancelled_close_fid, "PUT Cn-Fid") \
+       EM(netfs_trace_tcon_ref_put_cancelled_mid,      "PUT Cn-Mid") \
+       EM(netfs_trace_tcon_ref_put_mnt_ctx,            "PUT MntCtx") \
+       EM(netfs_trace_tcon_ref_put_reconnect_server,   "PUT Reconn") \
+       EM(netfs_trace_tcon_ref_put_tlink,              "PUT Tlink ") \
+       EM(netfs_trace_tcon_ref_see_cancelled_close,    "SEE Cn-Cls") \
+       EM(netfs_trace_tcon_ref_see_fscache_collision,  "SEE FV-CO!") \
+       EM(netfs_trace_tcon_ref_see_fscache_okay,       "SEE FV-Ok ") \
+       EM(netfs_trace_tcon_ref_see_fscache_relinq,     "SEE FV-Rlq") \
+       E_(netfs_trace_tcon_ref_see_umount,             "SEE Umount")
+
+#undef EM
+#undef E_
+
+/*
+ * Define those tracing enums.
+ */
+#ifndef __SMB3_DECLARE_TRACE_ENUMS_ONCE_ONLY
+#define __SMB3_DECLARE_TRACE_ENUMS_ONCE_ONLY
+
+#define EM(a, b) a,
+#define E_(a, b) a
+
+enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte);
+
+#undef EM
+#undef E_
+#endif
+
+/*
+ * Export enum symbols via userspace.
+ */
+#define EM(a, b) TRACE_DEFINE_ENUM(a);
+#define E_(a, b) TRACE_DEFINE_ENUM(a);
+
+smb3_tcon_ref_traces;
+
+#undef EM
+#undef E_
+
+/*
+ * Now redefine the EM() and E_() macros to map the enums to the strings that
+ * will be printed in the output.
  */
+#define EM(a, b)       { a, b },
+#define E_(a, b)       { a, b }
 
 /* For logging errors in read or write */
 DECLARE_EVENT_CLASS(smb3_rw_err_class,
@@ -1125,6 +1189,30 @@ DEFINE_SMB3_CREDIT_EVENT(waitff_credits);
 DEFINE_SMB3_CREDIT_EVENT(overflow_credits);
 DEFINE_SMB3_CREDIT_EVENT(set_credits);
 
+
+TRACE_EVENT(smb3_tcon_ref,
+           TP_PROTO(unsigned int tcon_debug_id, int ref,
+                    enum smb3_tcon_ref_trace trace),
+           TP_ARGS(tcon_debug_id, ref, trace),
+           TP_STRUCT__entry(
+                   __field(unsigned int,               tcon)
+                   __field(int,                        ref)
+                   __field(enum smb3_tcon_ref_trace,   trace)
+                            ),
+           TP_fast_assign(
+                   __entry->tcon       = tcon_debug_id;
+                   __entry->ref        = ref;
+                   __entry->trace      = trace;
+                          ),
+           TP_printk("TC=%08x %s r=%u",
+                     __entry->tcon,
+                     __print_symbolic(__entry->trace, smb3_tcon_ref_traces),
+                     __entry->ref)
+           );
+
+
+#undef EM
+#undef E_
 #endif /* _CIFS_TRACE_H */
 
 #undef TRACE_INCLUDE_PATH
index 994d70193432978de213a19a0f9933bd90e63671..ddf1a3aafee5c6f1e4f9c6ed4db54c48fcc8a84a 100644 (file)
@@ -909,12 +909,15 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
                        list_del_init(&mid->qhead);
                        mid->mid_flags |= MID_DELETED;
                }
+               spin_unlock(&server->mid_lock);
                cifs_server_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
                         __func__, mid->mid, mid->mid_state);
                rc = -EIO;
+               goto sync_mid_done;
        }
        spin_unlock(&server->mid_lock);
 
+sync_mid_done:
        release_mid(mid);
        return rc;
 }
@@ -1057,9 +1060,11 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
                index = (uint)atomic_inc_return(&ses->chan_seq);
                index %= ses->chan_count;
        }
+
+       server = ses->chans[index].server;
        spin_unlock(&ses->chan_lock);
 
-       return ses->chans[index].server;
+       return server;
 }
 
 int
index 1b594307c9d5a01e0b9d62b47b331dbd31c6dfaf..202ff912815604bd7b22700fc5ff598dd0a769ac 100644 (file)
@@ -711,7 +711,7 @@ struct smb2_close_rsp {
        __le16 StructureSize; /* 60 */
        __le16 Flags;
        __le32 Reserved;
-       struct_group(network_open_info,
+       struct_group_attr(network_open_info, __packed,
                __le64 CreationTime;
                __le64 LastAccessTime;
                __le64 LastWriteTime;
index 686b321c5a8bb5f0a1189023a3311e85aaf84c9e..f4e55199938d58023672fcd3006f7e97502fa6a5 100644 (file)
@@ -340,23 +340,24 @@ enum KSMBD_TREE_CONN_STATUS {
 /*
  * Share config flags.
  */
-#define KSMBD_SHARE_FLAG_INVALID               (0)
-#define KSMBD_SHARE_FLAG_AVAILABLE             BIT(0)
-#define KSMBD_SHARE_FLAG_BROWSEABLE            BIT(1)
-#define KSMBD_SHARE_FLAG_WRITEABLE             BIT(2)
-#define KSMBD_SHARE_FLAG_READONLY              BIT(3)
-#define KSMBD_SHARE_FLAG_GUEST_OK              BIT(4)
-#define KSMBD_SHARE_FLAG_GUEST_ONLY            BIT(5)
-#define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS       BIT(6)
-#define KSMBD_SHARE_FLAG_OPLOCKS               BIT(7)
-#define KSMBD_SHARE_FLAG_PIPE                  BIT(8)
-#define KSMBD_SHARE_FLAG_HIDE_DOT_FILES                BIT(9)
-#define KSMBD_SHARE_FLAG_INHERIT_OWNER         BIT(10)
-#define KSMBD_SHARE_FLAG_STREAMS               BIT(11)
-#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS       BIT(12)
-#define KSMBD_SHARE_FLAG_ACL_XATTR             BIT(13)
-#define KSMBD_SHARE_FLAG_UPDATE                        BIT(14)
-#define KSMBD_SHARE_FLAG_CROSSMNT              BIT(15)
+#define KSMBD_SHARE_FLAG_INVALID                       (0)
+#define KSMBD_SHARE_FLAG_AVAILABLE                     BIT(0)
+#define KSMBD_SHARE_FLAG_BROWSEABLE                    BIT(1)
+#define KSMBD_SHARE_FLAG_WRITEABLE                     BIT(2)
+#define KSMBD_SHARE_FLAG_READONLY                      BIT(3)
+#define KSMBD_SHARE_FLAG_GUEST_OK                      BIT(4)
+#define KSMBD_SHARE_FLAG_GUEST_ONLY                    BIT(5)
+#define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS               BIT(6)
+#define KSMBD_SHARE_FLAG_OPLOCKS                       BIT(7)
+#define KSMBD_SHARE_FLAG_PIPE                          BIT(8)
+#define KSMBD_SHARE_FLAG_HIDE_DOT_FILES                        BIT(9)
+#define KSMBD_SHARE_FLAG_INHERIT_OWNER                 BIT(10)
+#define KSMBD_SHARE_FLAG_STREAMS                       BIT(11)
+#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS               BIT(12)
+#define KSMBD_SHARE_FLAG_ACL_XATTR                     BIT(13)
+#define KSMBD_SHARE_FLAG_UPDATE                                BIT(14)
+#define KSMBD_SHARE_FLAG_CROSSMNT                      BIT(15)
+#define KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY       BIT(16)
 
 /*
  * Tree connect request flags.
index c0788188aa82fa39211f0be694a13f925408580c..c67fbc8d6683ef957b2b39601031c0aa25d22ac7 100644 (file)
@@ -167,20 +167,17 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
        int rc;
        bool is_chained = false;
 
-       if (conn->ops->allocate_rsp_buf(work))
-               return;
-
        if (conn->ops->is_transform_hdr &&
            conn->ops->is_transform_hdr(work->request_buf)) {
                rc = conn->ops->decrypt_req(work);
-               if (rc < 0) {
-                       conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
-                       goto send;
-               }
-
+               if (rc < 0)
+                       return;
                work->encrypted = true;
        }
 
+       if (conn->ops->allocate_rsp_buf(work))
+               return;
+
        rc = conn->ops->init_rsp_hdr(work);
        if (rc) {
                /* either uid or tid is not correct */
index 5723bbf372d7cc93c9e1b2dbdd5082c2824f85f8..355824151c2d88194b7013c2ffeabc074fbe6b87 100644 (file)
@@ -535,6 +535,10 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
        if (cmd == SMB2_QUERY_INFO_HE) {
                struct smb2_query_info_req *req;
 
+               if (get_rfc1002_len(work->request_buf) <
+                   offsetof(struct smb2_query_info_req, OutputBufferLength))
+                       return -EINVAL;
+
                req = smb2_get_msg(work->request_buf);
                if ((req->InfoType == SMB2_O_INFO_FILE &&
                     (req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
@@ -1984,7 +1988,12 @@ int smb2_tree_connect(struct ksmbd_work *work)
        write_unlock(&sess->tree_conns_lock);
        rsp->StructureSize = cpu_to_le16(16);
 out_err1:
-       rsp->Capabilities = 0;
+       if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE &&
+           test_share_config_flag(share,
+                                  KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY))
+               rsp->Capabilities = SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY;
+       else
+               rsp->Capabilities = 0;
        rsp->Reserved = 0;
        /* default manual caching */
        rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING;
@@ -3498,7 +3507,9 @@ int smb2_open(struct ksmbd_work *work)
        memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
 
        if (dh_info.type == DURABLE_REQ_V2 || dh_info.type == DURABLE_REQ) {
-               if (dh_info.type == DURABLE_REQ_V2 && dh_info.persistent)
+               if (dh_info.type == DURABLE_REQ_V2 && dh_info.persistent &&
+                   test_share_config_flag(work->tcon->share_conf,
+                                          KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY))
                        fp->is_persistent = true;
                else
                        fp->is_durable = true;
index 22f0f3db3ac92df2447e6b62646447d5ca1895a0..51b1b0bed616eea98a19e5e470f6aa929c8884b5 100644 (file)
@@ -754,10 +754,15 @@ retry:
                goto out4;
        }
 
+       /*
+        * explicitly handle file overwrite case, for compatibility with
+        * filesystems that may not support rename flags (e.g: fuse)
+        */
        if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry)) {
                err = -EEXIST;
                goto out4;
        }
+       flags &= ~(RENAME_NOREPLACE);
 
        if (old_child == trap) {
                err = -EINVAL;
index aa3411354e66d00c48db30adf73b34eedb84cb6d..16bd693d0b3aa23ce87af9cc1540e113a4c2a286 100644 (file)
@@ -48,6 +48,10 @@ static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
        gid_t i_gid;
        int err;
 
+       inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
+       if (inode->i_ino == 0)
+               return -EINVAL;
+
        err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->uid), &i_uid);
        if (err)
                return err;
@@ -58,7 +62,6 @@ static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
 
        i_uid_write(inode, i_uid);
        i_gid_write(inode, i_gid);
-       inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
        inode_set_mtime(inode, le32_to_cpu(sqsh_ino->mtime), 0);
        inode_set_atime(inode, inode_get_mtime_sec(inode), 0);
        inode_set_ctime(inode, inode_get_mtime_sec(inode), 0);
index 6b7652fb805057b8a155a0c94a3746fcb72eb5c7..7cd64021d453de7494f974ee21b77bc9a0838a35 100644 (file)
@@ -463,6 +463,8 @@ struct kernfs_node *sysfs_break_active_protection(struct kobject *kobj,
        kn = kernfs_find_and_get(kobj->sd, attr->name);
        if (kn)
                kernfs_break_active_protection(kn);
+       else
+               kobject_put(kobj);
        return kn;
 }
 EXPORT_SYMBOL_GPL(sysfs_break_active_protection);
index 894c6ca1e5002015b378ad8d6ec598de44c25ebe..a878cea70f4c9077612e0eefea159746e729fe5c 100644 (file)
@@ -37,6 +37,7 @@ static DEFINE_MUTEX(eventfs_mutex);
 
 struct eventfs_root_inode {
        struct eventfs_inode            ei;
+       struct inode                    *parent_inode;
        struct dentry                   *events_dir;
 };
 
@@ -68,11 +69,25 @@ enum {
        EVENTFS_SAVE_MODE       = BIT(16),
        EVENTFS_SAVE_UID        = BIT(17),
        EVENTFS_SAVE_GID        = BIT(18),
-       EVENTFS_TOPLEVEL        = BIT(19),
 };
 
 #define EVENTFS_MODE_MASK      (EVENTFS_SAVE_MODE - 1)
 
+static void free_ei_rcu(struct rcu_head *rcu)
+{
+       struct eventfs_inode *ei = container_of(rcu, struct eventfs_inode, rcu);
+       struct eventfs_root_inode *rei;
+
+       kfree(ei->entry_attrs);
+       kfree_const(ei->name);
+       if (ei->is_events) {
+               rei = get_root_inode(ei);
+               kfree(rei);
+       } else {
+               kfree(ei);
+       }
+}
+
 /*
  * eventfs_inode reference count management.
  *
@@ -84,18 +99,17 @@ enum {
 static void release_ei(struct kref *ref)
 {
        struct eventfs_inode *ei = container_of(ref, struct eventfs_inode, kref);
-       struct eventfs_root_inode *rei;
+       const struct eventfs_entry *entry;
 
        WARN_ON_ONCE(!ei->is_freed);
 
-       kfree(ei->entry_attrs);
-       kfree_const(ei->name);
-       if (ei->is_events) {
-               rei = get_root_inode(ei);
-               kfree_rcu(rei, ei.rcu);
-       } else {
-               kfree_rcu(ei, rcu);
+       for (int i = 0; i < ei->nr_entries; i++) {
+               entry = &ei->entries[i];
+               if (entry->release)
+                       entry->release(entry->name, ei->data);
        }
+
+       call_rcu(&ei->rcu, free_ei_rcu);
 }
 
 static inline void put_ei(struct eventfs_inode *ei)
@@ -112,6 +126,18 @@ static inline void free_ei(struct eventfs_inode *ei)
        }
 }
 
+/*
+ * Called when creation of an ei fails, do not call release() functions.
+ */
+static inline void cleanup_ei(struct eventfs_inode *ei)
+{
+       if (ei) {
+               /* Set nr_entries to 0 to prevent release() function being called */
+               ei->nr_entries = 0;
+               free_ei(ei);
+       }
+}
+
 static inline struct eventfs_inode *get_ei(struct eventfs_inode *ei)
 {
        if (ei)
@@ -181,21 +207,7 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,
         * determined by the parent directory.
         */
        if (dentry->d_inode->i_mode & S_IFDIR) {
-               /*
-                * The events directory dentry is never freed, unless its
-                * part of an instance that is deleted. It's attr is the
-                * default for its child files and directories.
-                * Do not update it. It's not used for its own mode or ownership.
-                */
-               if (ei->is_events) {
-                       /* But it still needs to know if it was modified */
-                       if (iattr->ia_valid & ATTR_UID)
-                               ei->attr.mode |= EVENTFS_SAVE_UID;
-                       if (iattr->ia_valid & ATTR_GID)
-                               ei->attr.mode |= EVENTFS_SAVE_GID;
-               } else {
-                       update_attr(&ei->attr, iattr);
-               }
+               update_attr(&ei->attr, iattr);
 
        } else {
                name = dentry->d_name.name;
@@ -213,18 +225,25 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,
        return ret;
 }
 
-static void update_top_events_attr(struct eventfs_inode *ei, struct super_block *sb)
+static void update_events_attr(struct eventfs_inode *ei, struct super_block *sb)
 {
-       struct inode *root;
+       struct eventfs_root_inode *rei;
+       struct inode *parent;
 
-       /* Only update if the "events" was on the top level */
-       if (!ei || !(ei->attr.mode & EVENTFS_TOPLEVEL))
-               return;
+       rei = get_root_inode(ei);
 
-       /* Get the tracefs root inode. */
-       root = d_inode(sb->s_root);
-       ei->attr.uid = root->i_uid;
-       ei->attr.gid = root->i_gid;
+       /* Use the parent inode permissions unless root set its permissions */
+       parent = rei->parent_inode;
+
+       if (rei->ei.attr.mode & EVENTFS_SAVE_UID)
+               ei->attr.uid = rei->ei.attr.uid;
+       else
+               ei->attr.uid = parent->i_uid;
+
+       if (rei->ei.attr.mode & EVENTFS_SAVE_GID)
+               ei->attr.gid = rei->ei.attr.gid;
+       else
+               ei->attr.gid = parent->i_gid;
 }
 
 static void set_top_events_ownership(struct inode *inode)
@@ -233,10 +252,10 @@ static void set_top_events_ownership(struct inode *inode)
        struct eventfs_inode *ei = ti->private;
 
        /* The top events directory doesn't get automatically updated */
-       if (!ei || !ei->is_events || !(ei->attr.mode & EVENTFS_TOPLEVEL))
+       if (!ei || !ei->is_events)
                return;
 
-       update_top_events_attr(ei, inode->i_sb);
+       update_events_attr(ei, inode->i_sb);
 
        if (!(ei->attr.mode & EVENTFS_SAVE_UID))
                inode->i_uid = ei->attr.uid;
@@ -265,7 +284,7 @@ static int eventfs_permission(struct mnt_idmap *idmap,
        return generic_permission(idmap, inode, mask);
 }
 
-static const struct inode_operations eventfs_root_dir_inode_operations = {
+static const struct inode_operations eventfs_dir_inode_operations = {
        .lookup         = eventfs_root_lookup,
        .setattr        = eventfs_set_attr,
        .getattr        = eventfs_get_attr,
@@ -282,6 +301,35 @@ static const struct file_operations eventfs_file_operations = {
        .llseek         = generic_file_llseek,
 };
 
+/*
+ * On a remount of tracefs, if UID or GID options are set, then
+ * the mount point inode permissions should be used.
+ * Reset the saved permission flags appropriately.
+ */
+void eventfs_remount(struct tracefs_inode *ti, bool update_uid, bool update_gid)
+{
+       struct eventfs_inode *ei = ti->private;
+
+       if (!ei)
+               return;
+
+       if (update_uid)
+               ei->attr.mode &= ~EVENTFS_SAVE_UID;
+
+       if (update_gid)
+               ei->attr.mode &= ~EVENTFS_SAVE_GID;
+
+       if (!ei->entry_attrs)
+               return;
+
+       for (int i = 0; i < ei->nr_entries; i++) {
+               if (update_uid)
+                       ei->entry_attrs[i].mode &= ~EVENTFS_SAVE_UID;
+               if (update_gid)
+                       ei->entry_attrs[i].mode &= ~EVENTFS_SAVE_GID;
+       }
+}
+
 /* Return the evenfs_inode of the "events" directory */
 static struct eventfs_inode *eventfs_find_events(struct dentry *dentry)
 {
@@ -304,7 +352,7 @@ static struct eventfs_inode *eventfs_find_events(struct dentry *dentry)
                // Walk upwards until you find the events inode
        } while (!ei->is_events);
 
-       update_top_events_attr(ei, dentry->d_sb);
+       update_events_attr(ei, dentry->d_sb);
 
        return ei;
 }
@@ -410,7 +458,7 @@ static struct dentry *lookup_dir_entry(struct dentry *dentry,
        update_inode_attr(dentry, inode, &ei->attr,
                          S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
 
-       inode->i_op = &eventfs_root_dir_inode_operations;
+       inode->i_op = &eventfs_dir_inode_operations;
        inode->i_fop = &eventfs_file_operations;
 
        /* All directories will have the same inode number */
@@ -734,7 +782,7 @@ struct eventfs_inode *eventfs_create_dir(const char *name, struct eventfs_inode
 
        /* Was the parent freed? */
        if (list_empty(&ei->list)) {
-               free_ei(ei);
+               cleanup_ei(ei);
                ei = NULL;
        }
        return ei;
@@ -781,6 +829,7 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
        // Note: we have a ref to the dentry from tracefs_start_creating()
        rei = get_root_inode(ei);
        rei->events_dir = dentry;
+       rei->parent_inode = d_inode(dentry->d_sb->s_root);
 
        ei->entries = entries;
        ei->nr_entries = size;
@@ -790,29 +839,26 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
        uid = d_inode(dentry->d_parent)->i_uid;
        gid = d_inode(dentry->d_parent)->i_gid;
 
-       /*
-        * If the events directory is of the top instance, then parent
-        * is NULL. Set the attr.mode to reflect this and its permissions will
-        * default to the tracefs root dentry.
-        */
-       if (!parent)
-               ei->attr.mode = EVENTFS_TOPLEVEL;
-
-       /* This is used as the default ownership of the files and directories */
        ei->attr.uid = uid;
        ei->attr.gid = gid;
 
+       /*
+        * When the "events" directory is created, it takes on the
+        * permissions of its parent. But can be reset on remount.
+        */
+       ei->attr.mode |= EVENTFS_SAVE_UID | EVENTFS_SAVE_GID;
+
        INIT_LIST_HEAD(&ei->children);
        INIT_LIST_HEAD(&ei->list);
 
        ti = get_tracefs(inode);
-       ti->flags |= TRACEFS_EVENT_INODE | TRACEFS_EVENT_TOP_INODE;
+       ti->flags |= TRACEFS_EVENT_INODE;
        ti->private = ei;
 
        inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
        inode->i_uid = uid;
        inode->i_gid = gid;
-       inode->i_op = &eventfs_root_dir_inode_operations;
+       inode->i_op = &eventfs_dir_inode_operations;
        inode->i_fop = &eventfs_file_operations;
 
        dentry->d_fsdata = get_ei(ei);
@@ -835,7 +881,7 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
        return ei;
 
  fail:
-       free_ei(ei);
+       cleanup_ei(ei);
        tracefs_failed_creating(dentry);
        return ERR_PTR(-ENOMEM);
 }
index 5545e6bf7d26c4300b70802f40d1f796263624df..417c840e6403338f0708640527442c87bfe492e7 100644 (file)
@@ -30,20 +30,47 @@ static struct vfsmount *tracefs_mount;
 static int tracefs_mount_count;
 static bool tracefs_registered;
 
+/*
+ * Keep track of all tracefs_inodes in order to update their
+ * flags if necessary on a remount.
+ */
+static DEFINE_SPINLOCK(tracefs_inode_lock);
+static LIST_HEAD(tracefs_inodes);
+
 static struct inode *tracefs_alloc_inode(struct super_block *sb)
 {
        struct tracefs_inode *ti;
+       unsigned long flags;
 
        ti = kmem_cache_alloc(tracefs_inode_cachep, GFP_KERNEL);
        if (!ti)
                return NULL;
 
+       spin_lock_irqsave(&tracefs_inode_lock, flags);
+       list_add_rcu(&ti->list, &tracefs_inodes);
+       spin_unlock_irqrestore(&tracefs_inode_lock, flags);
+
        return &ti->vfs_inode;
 }
 
+static void tracefs_free_inode_rcu(struct rcu_head *rcu)
+{
+       struct tracefs_inode *ti;
+
+       ti = container_of(rcu, struct tracefs_inode, rcu);
+       kmem_cache_free(tracefs_inode_cachep, ti);
+}
+
 static void tracefs_free_inode(struct inode *inode)
 {
-       kmem_cache_free(tracefs_inode_cachep, get_tracefs(inode));
+       struct tracefs_inode *ti = get_tracefs(inode);
+       unsigned long flags;
+
+       spin_lock_irqsave(&tracefs_inode_lock, flags);
+       list_del_rcu(&ti->list);
+       spin_unlock_irqrestore(&tracefs_inode_lock, flags);
+
+       call_rcu(&ti->rcu, tracefs_free_inode_rcu);
 }
 
 static ssize_t default_read_file(struct file *file, char __user *buf,
@@ -153,16 +180,39 @@ static void set_tracefs_inode_owner(struct inode *inode)
 {
        struct tracefs_inode *ti = get_tracefs(inode);
        struct inode *root_inode = ti->private;
+       kuid_t uid;
+       kgid_t gid;
+
+       uid = root_inode->i_uid;
+       gid = root_inode->i_gid;
+
+       /*
+        * If the root is not the mount point, then check the root's
+        * permissions. If it was never set, then default to the
+        * mount point.
+        */
+       if (root_inode != d_inode(root_inode->i_sb->s_root)) {
+               struct tracefs_inode *rti;
+
+               rti = get_tracefs(root_inode);
+               root_inode = d_inode(root_inode->i_sb->s_root);
+
+               if (!(rti->flags & TRACEFS_UID_PERM_SET))
+                       uid = root_inode->i_uid;
+
+               if (!(rti->flags & TRACEFS_GID_PERM_SET))
+                       gid = root_inode->i_gid;
+       }
 
        /*
         * If this inode has never been referenced, then update
         * the permissions to the superblock.
         */
        if (!(ti->flags & TRACEFS_UID_PERM_SET))
-               inode->i_uid = root_inode->i_uid;
+               inode->i_uid = uid;
 
        if (!(ti->flags & TRACEFS_GID_PERM_SET))
-               inode->i_gid = root_inode->i_gid;
+               inode->i_gid = gid;
 }
 
 static int tracefs_permission(struct mnt_idmap *idmap,
@@ -313,6 +363,8 @@ static int tracefs_apply_options(struct super_block *sb, bool remount)
        struct tracefs_fs_info *fsi = sb->s_fs_info;
        struct inode *inode = d_inode(sb->s_root);
        struct tracefs_mount_opts *opts = &fsi->mount_opts;
+       struct tracefs_inode *ti;
+       bool update_uid, update_gid;
        umode_t tmp_mode;
 
        /*
@@ -332,6 +384,25 @@ static int tracefs_apply_options(struct super_block *sb, bool remount)
        if (!remount || opts->opts & BIT(Opt_gid))
                inode->i_gid = opts->gid;
 
+       if (remount && (opts->opts & BIT(Opt_uid) || opts->opts & BIT(Opt_gid))) {
+
+               update_uid = opts->opts & BIT(Opt_uid);
+               update_gid = opts->opts & BIT(Opt_gid);
+
+               rcu_read_lock();
+               list_for_each_entry_rcu(ti, &tracefs_inodes, list) {
+                       if (update_uid)
+                               ti->flags &= ~TRACEFS_UID_PERM_SET;
+
+                       if (update_gid)
+                               ti->flags &= ~TRACEFS_GID_PERM_SET;
+
+                       if (ti->flags & TRACEFS_EVENT_INODE)
+                               eventfs_remount(ti, update_uid, update_gid);
+               }
+               rcu_read_unlock();
+       }
+
        return 0;
 }
 
@@ -398,7 +469,22 @@ static int tracefs_d_revalidate(struct dentry *dentry, unsigned int flags)
        return !(ei && ei->is_freed);
 }
 
+static void tracefs_d_iput(struct dentry *dentry, struct inode *inode)
+{
+       struct tracefs_inode *ti = get_tracefs(inode);
+
+       /*
+        * This inode is being freed and cannot be used for
+        * eventfs. Clear the flag so that it doesn't call into
+        * eventfs during the remount flag updates. The eventfs_inode
+        * gets freed after an RCU cycle, so the content will still
+        * be safe if the iteration is going on now.
+        */
+       ti->flags &= ~TRACEFS_EVENT_INODE;
+}
+
 static const struct dentry_operations tracefs_dentry_operations = {
+       .d_iput = tracefs_d_iput,
        .d_revalidate = tracefs_d_revalidate,
        .d_release = tracefs_d_release,
 };
index 15c26f9aaad4df1fe3d509061ba6cd3b437ae76e..f704d8348357ed8f8a2a11195718b716e7277244 100644 (file)
@@ -4,15 +4,18 @@
 
 enum {
        TRACEFS_EVENT_INODE             = BIT(1),
-       TRACEFS_EVENT_TOP_INODE         = BIT(2),
-       TRACEFS_GID_PERM_SET            = BIT(3),
-       TRACEFS_UID_PERM_SET            = BIT(4),
-       TRACEFS_INSTANCE_INODE          = BIT(5),
+       TRACEFS_GID_PERM_SET            = BIT(2),
+       TRACEFS_UID_PERM_SET            = BIT(3),
+       TRACEFS_INSTANCE_INODE          = BIT(4),
 };
 
 struct tracefs_inode {
-       struct inode            vfs_inode;
+       union {
+               struct inode            vfs_inode;
+               struct rcu_head         rcu;
+       };
        /* The below gets initialized with memset_after(ti, 0, vfs_inode) */
+       struct list_head        list;
        unsigned long           flags;
        void                    *private;
 };
@@ -73,6 +76,7 @@ struct dentry *tracefs_end_creating(struct dentry *dentry);
 struct dentry *tracefs_failed_creating(struct dentry *dentry);
 struct inode *tracefs_get_inode(struct super_block *sb);
 
+void eventfs_remount(struct tracefs_inode *ti, bool update_uid, bool update_gid);
 void eventfs_d_release(struct dentry *dentry);
 
 #endif /* _TRACEFS_INTERNAL_H */
index 0c0695763bea394aadf9ed26abd8fb3bedc714cf..d4f581c1e21da54f340bdfb8a4e846e59989e3aa 100644 (file)
@@ -294,5 +294,13 @@ do {                                                                       \
 #define io_stop_wc() do { } while (0)
 #endif
 
+/*
+ * Architectures that guarantee an implicit smp_mb() in switch_mm()
+ * can override smp_mb__after_switch_mm.
+ */
+#ifndef smp_mb__after_switch_mm
+# define smp_mb__after_switch_mm()     smp_mb()
+#endif
+
 #endif /* !__ASSEMBLY__ */
 #endif /* __ASM_GENERIC_BARRIER_H */
index d21838835abdadbd98b773c9569921954a9a7778..d58fc022ec466e2041c081a14783844daadbb84c 100644 (file)
@@ -49,13 +49,17 @@ struct amd_aperf_mperf {
  * @lowest_perf: the absolute lowest performance level of the processor
  * @prefcore_ranking: the preferred core ranking, the higher value indicates a higher
  *               priority.
- * @max_freq: the frequency that mapped to highest_perf
- * @min_freq: the frequency that mapped to lowest_perf
- * @nominal_freq: the frequency that mapped to nominal_perf
- * @lowest_nonlinear_freq: the frequency that mapped to lowest_nonlinear_perf
+ * @min_limit_perf: Cached value of the performance corresponding to policy->min
+ * @max_limit_perf: Cached value of the performance corresponding to policy->max
+ * @min_limit_freq: Cached value of policy->min (in khz)
+ * @max_limit_freq: Cached value of policy->max (in khz)
+ * @max_freq: the frequency (in khz) that mapped to highest_perf
+ * @min_freq: the frequency (in khz) that mapped to lowest_perf
+ * @nominal_freq: the frequency (in khz) that mapped to nominal_perf
+ * @lowest_nonlinear_freq: the frequency (in khz) that mapped to lowest_nonlinear_perf
  * @cur: Difference of Aperf/Mperf/tsc count between last and current sample
  * @prev: Last Aperf/Mperf/tsc count value read from register
- * @freq: current cpu frequency value
+ * @freq: current cpu frequency value (in khz)
  * @boost_supported: check whether the Processor or SBIOS supports boost mode
  * @hw_prefcore: check whether HW supports preferred core featue.
  *               Only when hw_prefcore and early prefcore param are true,
@@ -124,4 +128,10 @@ static const char * const amd_pstate_mode_string[] = {
        [AMD_PSTATE_GUIDED]      = "guided",
        NULL,
 };
+
+struct quirk_entry {
+       u32 nominal_freq;
+       u32 lowest_freq;
+};
+
 #endif /* _LINUX_AMD_PSTATE_H */
index 172c918799995f8ce6ed285bc5a8ea3341ddb6ed..69e7da33ca49a6f5caeec85c56728069cc61a69e 100644 (file)
@@ -128,6 +128,8 @@ typedef unsigned int __bitwise blk_mode_t;
 #define BLK_OPEN_WRITE_IOCTL   ((__force blk_mode_t)(1 << 4))
 /* open is exclusive wrt all other BLK_OPEN_WRITE opens to the device */
 #define BLK_OPEN_RESTRICT_WRITES       ((__force blk_mode_t)(1 << 5))
+/* return partition scanning errors */
+#define BLK_OPEN_STRICT_SCAN   ((__force blk_mode_t)(1 << 6))
 
 struct gendisk {
        /*
index e5ee2c694401e0972d4a644f01ca523f63f83475..3f4b4ac527ca28c66119cf00fc13083633ec80a3 100644 (file)
@@ -288,7 +288,12 @@ int __init xbc_init(const char *buf, size_t size, const char **emsg, int *epos);
 int __init xbc_get_info(int *node_size, size_t *data_size);
 
 /* XBC cleanup data structures */
-void __init xbc_exit(void);
+void __init _xbc_exit(bool early);
+
+static inline void xbc_exit(void)
+{
+       _xbc_exit(false);
+}
 
 /* XBC embedded bootconfig data in kernel */
 #ifdef CONFIG_BOOT_CONFIG_EMBED
index 00623f4de5e195d5a4b880db633b1bfd335f34fc..0fa56d672532157290264c8dfa0a79dab94657bb 100644 (file)
@@ -286,6 +286,11 @@ static inline int clk_rate_exclusive_get(struct clk *clk)
        return 0;
 }
 
+static inline int devm_clk_rate_exclusive_get(struct device *dev, struct clk *clk)
+{
+       return 0;
+}
+
 static inline void clk_rate_exclusive_put(struct clk *clk) {}
 
 #endif
index 272e4e79e15c48db487feba3b7e6103e71b21e8d..861c3bfc5f1700db69d90168c239a935ebad76ca 100644 (file)
@@ -221,7 +221,18 @@ void cpuhp_report_idle_dead(void);
 static inline void cpuhp_report_idle_dead(void) { }
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 
+#ifdef CONFIG_CPU_MITIGATIONS
 extern bool cpu_mitigations_off(void);
 extern bool cpu_mitigations_auto_nosmt(void);
+#else
+static inline bool cpu_mitigations_off(void)
+{
+       return true;
+}
+static inline bool cpu_mitigations_auto_nosmt(void)
+{
+       return false;
+}
+#endif
 
 #endif /* _LINUX_CPU_H_ */
index 224645f17c333b2311573197a28b41701eb35f92..297231854ada51ebeb5a8976db22e0e4702e5adb 100644 (file)
@@ -607,6 +607,31 @@ static inline void eth_hw_addr_gen(struct net_device *dev, const u8 *base_addr,
        eth_hw_addr_set(dev, addr);
 }
 
+/**
+ * eth_skb_pkt_type - Assign packet type if destination address does not match
+ * @skb: Assigned a packet type if address does not match @dev address
+ * @dev: Network device used to compare packet address against
+ *
+ * If the destination MAC address of the packet does not match the network
+ * device address, assign an appropriate packet type.
+ */
+static inline void eth_skb_pkt_type(struct sk_buff *skb,
+                                   const struct net_device *dev)
+{
+       const struct ethhdr *eth = eth_hdr(skb);
+
+       if (unlikely(!ether_addr_equal_64bits(eth->h_dest, dev->dev_addr))) {
+               if (unlikely(is_multicast_ether_addr_64bits(eth->h_dest))) {
+                       if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast))
+                               skb->pkt_type = PACKET_BROADCAST;
+                       else
+                               skb->pkt_type = PACKET_MULTICAST;
+               } else {
+                       skb->pkt_type = PACKET_OTHERHOST;
+               }
+       }
+}
+
 /**
  * eth_skb_pad - Pad buffer to mininum number of octets for Ethernet frame
  * @skb: Buffer to pad
index c99bc3df2d28e35f73b21d62ca50f4a53c515e1b..219ee7a76874439e9a2ecda7a402a7a9e741e0be 100644 (file)
@@ -963,6 +963,7 @@ bool bpf_jit_supports_far_kfunc_call(void);
 bool bpf_jit_supports_exceptions(void);
 bool bpf_jit_supports_ptr_xchg(void);
 bool bpf_jit_supports_arena(void);
+u64 bpf_arch_uaddress_limit(void);
 void arch_bpf_stack_walk(bool (*consume_fn)(void *cookie, u64 ip, u64 sp, u64 bp), void *cookie);
 bool bpf_helper_changes_pkt_data(void *func);
 
index 5c28298a98bec8146e8b2dad45aa946aff780f03..366243ee96096d6fc134ae73a6d3209c8e4df4a1 100644 (file)
@@ -10,6 +10,7 @@
 #define __QCOM_QSEECOM_H
 
 #include <linux/auxiliary_bus.h>
+#include <linux/dma-mapping.h>
 #include <linux/types.h>
 
 #include <linux/firmware/qcom/qcom_scm.h>
@@ -24,12 +25,57 @@ struct qseecom_client {
        u32 app_id;
 };
 
+/**
+ * qseecom_scm_dev() - Get the SCM device associated with the QSEECOM client.
+ * @client: The QSEECOM client device.
+ *
+ * Returns the SCM device under which the provided QSEECOM client device
+ * operates. This function is intended to be used for DMA allocations.
+ */
+static inline struct device *qseecom_scm_dev(struct qseecom_client *client)
+{
+       return client->aux_dev.dev.parent->parent;
+}
+
+/**
+ * qseecom_dma_alloc() - Allocate DMA memory for a QSEECOM client.
+ * @client:     The QSEECOM client to allocate the memory for.
+ * @size:       The number of bytes to allocate.
+ * @dma_handle: Pointer to where the DMA address should be stored.
+ * @gfp:        Allocation flags.
+ *
+ * Wrapper function for dma_alloc_coherent(), allocating DMA memory usable for
+ * TZ/QSEECOM communication. Refer to dma_alloc_coherent() for details.
+ */
+static inline void *qseecom_dma_alloc(struct qseecom_client *client, size_t size,
+                                     dma_addr_t *dma_handle, gfp_t gfp)
+{
+       return dma_alloc_coherent(qseecom_scm_dev(client), size, dma_handle, gfp);
+}
+
+/**
+ * dma_free_coherent() - Free QSEECOM DMA memory.
+ * @client:     The QSEECOM client for which the memory has been allocated.
+ * @size:       The number of bytes allocated.
+ * @cpu_addr:   Virtual memory address to free.
+ * @dma_handle: DMA memory address to free.
+ *
+ * Wrapper function for dma_free_coherent(), freeing memory previously
+ * allocated with qseecom_dma_alloc(). Refer to dma_free_coherent() for
+ * details.
+ */
+static inline void qseecom_dma_free(struct qseecom_client *client, size_t size,
+                                   void *cpu_addr, dma_addr_t dma_handle)
+{
+       return dma_free_coherent(qseecom_scm_dev(client), size, cpu_addr, dma_handle);
+}
+
 /**
  * qcom_qseecom_app_send() - Send to and receive data from a given QSEE app.
  * @client:   The QSEECOM client associated with the target app.
- * @req:      Request buffer sent to the app (must be DMA-mappable).
+ * @req:      DMA address of the request buffer sent to the app.
  * @req_size: Size of the request buffer.
- * @rsp:      Response buffer, written to by the app (must be DMA-mappable).
+ * @rsp:      DMA address of the response buffer, written to by the app.
  * @rsp_size: Size of the response buffer.
  *
  * Sends a request to the QSEE app associated with the given client and read
@@ -43,8 +89,9 @@ struct qseecom_client {
  *
  * Return: Zero on success, nonzero on failure.
  */
-static inline int qcom_qseecom_app_send(struct qseecom_client *client, void *req, size_t req_size,
-                                       void *rsp, size_t rsp_size)
+static inline int qcom_qseecom_app_send(struct qseecom_client *client,
+                                       dma_addr_t req, size_t req_size,
+                                       dma_addr_t rsp, size_t rsp_size)
 {
        return qcom_scm_qseecom_app_send(client->app_id, req, req_size, rsp, rsp_size);
 }
index ccaf288460546a8617a9c7efc5132de8d5fca4e7..aaa19f93ac4306f33e817163cc4eca075cf0b4d4 100644 (file)
@@ -118,8 +118,8 @@ bool qcom_scm_lmh_dcvsh_available(void);
 #ifdef CONFIG_QCOM_QSEECOM
 
 int qcom_scm_qseecom_app_get_id(const char *app_name, u32 *app_id);
-int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size, void *rsp,
-                             size_t rsp_size);
+int qcom_scm_qseecom_app_send(u32 app_id, dma_addr_t req, size_t req_size,
+                             dma_addr_t rsp, size_t rsp_size);
 
 #else /* CONFIG_QCOM_QSEECOM */
 
@@ -128,9 +128,9 @@ static inline int qcom_scm_qseecom_app_get_id(const char *app_name, u32 *app_id)
        return -EINVAL;
 }
 
-static inline int qcom_scm_qseecom_app_send(u32 app_id, void *req,
-                                           size_t req_size, void *rsp,
-                                           size_t rsp_size)
+static inline int qcom_scm_qseecom_app_send(u32 app_id,
+                                           dma_addr_t req, size_t req_size,
+                                           dma_addr_t rsp, size_t rsp_size)
 {
        return -EINVAL;
 }
index 6c75c8bd44a0bb627020ba267c3d0debb2379ba4..1a14e239221f7e9aec06b510d450c9f30b34fc2c 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef __LINUX_GPIO_PROPERTY_H
 #define __LINUX_GPIO_PROPERTY_H
 
-#include <dt-bindings/gpio/gpio.h> /* for GPIO_* flags */
 #include <linux/property.h>
 
 #define PROPERTY_ENTRY_GPIO(_name_, _chip_node_, _idx_, _flags_) \
index 7b0ee64225de9cefebaf63e0d759c082684e3ab5..b6bdaa18b9e9d44583cd245c662e6c2bfdae3825 100644 (file)
@@ -1223,14 +1223,16 @@ static inline void page_mapcount_reset(struct page *page)
  * a large folio, it includes the number of times this page is mapped
  * as part of that folio.
  *
- * The result is undefined for pages which cannot be mapped into userspace.
- * For example SLAB or special types of pages. See function page_has_type().
- * They use this field in struct page differently.
+ * Will report 0 for pages which cannot be mapped into userspace, eg
+ * slab, page tables and similar.
  */
 static inline int page_mapcount(struct page *page)
 {
        int mapcount = atomic_read(&page->_mapcount) + 1;
 
+       /* Handle page_has_type() pages */
+       if (mapcount < 0)
+               mapcount = 0;
        if (unlikely(PageCompound(page)))
                mapcount += folio_entire_mapcount(page_folio(page));
 
index 652d77805e99dfb2adf31def151a26466eff571c..4bf1c25fd1dc566cccf51742286243bace192dad 100644 (file)
@@ -190,7 +190,6 @@ enum pageflags {
 
        /* At least one page in this folio has the hwpoison flag set */
        PG_has_hwpoisoned = PG_error,
-       PG_hugetlb = PG_active,
        PG_large_rmappable = PG_workingset, /* anon or file-backed */
 };
 
@@ -458,30 +457,51 @@ static __always_inline int TestClearPage##uname(struct page *page)        \
        TESTSETFLAG(uname, lname, policy)                               \
        TESTCLEARFLAG(uname, lname, policy)
 
+#define FOLIO_TEST_FLAG_FALSE(name)                                    \
+static inline bool folio_test_##name(const struct folio *folio)                \
+{ return false; }
+#define FOLIO_SET_FLAG_NOOP(name)                                      \
+static inline void folio_set_##name(struct folio *folio) { }
+#define FOLIO_CLEAR_FLAG_NOOP(name)                                    \
+static inline void folio_clear_##name(struct folio *folio) { }
+#define __FOLIO_SET_FLAG_NOOP(name)                                    \
+static inline void __folio_set_##name(struct folio *folio) { }
+#define __FOLIO_CLEAR_FLAG_NOOP(name)                                  \
+static inline void __folio_clear_##name(struct folio *folio) { }
+#define FOLIO_TEST_SET_FLAG_FALSE(name)                                        \
+static inline bool folio_test_set_##name(struct folio *folio)          \
+{ return false; }
+#define FOLIO_TEST_CLEAR_FLAG_FALSE(name)                              \
+static inline bool folio_test_clear_##name(struct folio *folio)                \
+{ return false; }
+
+#define FOLIO_FLAG_FALSE(name)                                         \
+FOLIO_TEST_FLAG_FALSE(name)                                            \
+FOLIO_SET_FLAG_NOOP(name)                                              \
+FOLIO_CLEAR_FLAG_NOOP(name)
+
 #define TESTPAGEFLAG_FALSE(uname, lname)                               \
-static inline bool folio_test_##lname(const struct folio *folio) { return false; } \
+FOLIO_TEST_FLAG_FALSE(lname)                                           \
 static inline int Page##uname(const struct page *page) { return 0; }
 
 #define SETPAGEFLAG_NOOP(uname, lname)                                 \
-static inline void folio_set_##lname(struct folio *folio) { }          \
+FOLIO_SET_FLAG_NOOP(lname)                                             \
 static inline void SetPage##uname(struct page *page) {  }
 
 #define CLEARPAGEFLAG_NOOP(uname, lname)                               \
-static inline void folio_clear_##lname(struct folio *folio) { }                \
+FOLIO_CLEAR_FLAG_NOOP(lname)                                           \
 static inline void ClearPage##uname(struct page *page) {  }
 
 #define __CLEARPAGEFLAG_NOOP(uname, lname)                             \
-static inline void __folio_clear_##lname(struct folio *folio) { }      \
+__FOLIO_CLEAR_FLAG_NOOP(lname)                                         \
 static inline void __ClearPage##uname(struct page *page) {  }
 
 #define TESTSETFLAG_FALSE(uname, lname)                                        \
-static inline bool folio_test_set_##lname(struct folio *folio)         \
-{ return 0; }                                                          \
+FOLIO_TEST_SET_FLAG_FALSE(lname)                                       \
 static inline int TestSetPage##uname(struct page *page) { return 0; }
 
 #define TESTCLEARFLAG_FALSE(uname, lname)                              \
-static inline bool folio_test_clear_##lname(struct folio *folio)       \
-{ return 0; }                                                          \
+FOLIO_TEST_CLEAR_FLAG_FALSE(lname)                                     \
 static inline int TestClearPage##uname(struct page *page) { return 0; }
 
 #define PAGEFLAG_FALSE(uname, lname) TESTPAGEFLAG_FALSE(uname, lname)  \
@@ -855,29 +875,6 @@ TESTPAGEFLAG_FALSE(LargeRmappable, large_rmappable)
 
 #define PG_head_mask ((1UL << PG_head))
 
-#ifdef CONFIG_HUGETLB_PAGE
-int PageHuge(const struct page *page);
-SETPAGEFLAG(HugeTLB, hugetlb, PF_SECOND)
-CLEARPAGEFLAG(HugeTLB, hugetlb, PF_SECOND)
-
-/**
- * folio_test_hugetlb - Determine if the folio belongs to hugetlbfs
- * @folio: The folio to test.
- *
- * Context: Any context.  Caller should have a reference on the folio to
- * prevent it from being turned into a tail page.
- * Return: True for hugetlbfs folios, false for anon folios or folios
- * belonging to other filesystems.
- */
-static inline bool folio_test_hugetlb(const struct folio *folio)
-{
-       return folio_test_large(folio) &&
-               test_bit(PG_hugetlb, const_folio_flags(folio, 1));
-}
-#else
-TESTPAGEFLAG_FALSE(Huge, hugetlb)
-#endif
-
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 /*
  * PageHuge() only returns true for hugetlbfs pages, but not for
@@ -933,34 +930,23 @@ PAGEFLAG_FALSE(HasHWPoisoned, has_hwpoisoned)
        TESTSCFLAG_FALSE(HasHWPoisoned, has_hwpoisoned)
 #endif
 
-/*
- * Check if a page is currently marked HWPoisoned. Note that this check is
- * best effort only and inherently racy: there is no way to synchronize with
- * failing hardware.
- */
-static inline bool is_page_hwpoison(struct page *page)
-{
-       if (PageHWPoison(page))
-               return true;
-       return PageHuge(page) && PageHWPoison(compound_head(page));
-}
-
 /*
  * For pages that are never mapped to userspace (and aren't PageSlab),
  * page_type may be used.  Because it is initialised to -1, we invert the
  * sense of the bit, so __SetPageFoo *clears* the bit used for PageFoo, and
  * __ClearPageFoo *sets* the bit used for PageFoo.  We reserve a few high and
- * low bits so that an underflow or overflow of page_mapcount() won't be
+ * low bits so that an underflow or overflow of _mapcount won't be
  * mistaken for a page type value.
  */
 
 #define PAGE_TYPE_BASE 0xf0000000
-/* Reserve             0x0000007f to catch underflows of page_mapcount */
+/* Reserve             0x0000007f to catch underflows of _mapcount */
 #define PAGE_MAPCOUNT_RESERVE  -128
 #define PG_buddy       0x00000080
 #define PG_offline     0x00000100
 #define PG_table       0x00000200
 #define PG_guard       0x00000400
+#define PG_hugetlb     0x00000800
 
 #define PageType(page, flag)                                           \
        ((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE)
@@ -977,35 +963,38 @@ static inline int page_has_type(const struct page *page)
        return page_type_has_type(page->page_type);
 }
 
+#define FOLIO_TYPE_OPS(lname, fname)                                   \
+static __always_inline bool folio_test_##fname(const struct folio *folio)\
+{                                                                      \
+       return folio_test_type(folio, PG_##lname);                      \
+}                                                                      \
+static __always_inline void __folio_set_##fname(struct folio *folio)   \
+{                                                                      \
+       VM_BUG_ON_FOLIO(!folio_test_type(folio, 0), folio);             \
+       folio->page.page_type &= ~PG_##lname;                           \
+}                                                                      \
+static __always_inline void __folio_clear_##fname(struct folio *folio) \
+{                                                                      \
+       VM_BUG_ON_FOLIO(!folio_test_##fname(folio), folio);             \
+       folio->page.page_type |= PG_##lname;                            \
+}
+
 #define PAGE_TYPE_OPS(uname, lname, fname)                             \
+FOLIO_TYPE_OPS(lname, fname)                                           \
 static __always_inline int Page##uname(const struct page *page)                \
 {                                                                      \
        return PageType(page, PG_##lname);                              \
 }                                                                      \
-static __always_inline int folio_test_##fname(const struct folio *folio)\
-{                                                                      \
-       return folio_test_type(folio, PG_##lname);                      \
-}                                                                      \
 static __always_inline void __SetPage##uname(struct page *page)                \
 {                                                                      \
        VM_BUG_ON_PAGE(!PageType(page, 0), page);                       \
        page->page_type &= ~PG_##lname;                                 \
 }                                                                      \
-static __always_inline void __folio_set_##fname(struct folio *folio)   \
-{                                                                      \
-       VM_BUG_ON_FOLIO(!folio_test_type(folio, 0), folio);             \
-       folio->page.page_type &= ~PG_##lname;                           \
-}                                                                      \
 static __always_inline void __ClearPage##uname(struct page *page)      \
 {                                                                      \
        VM_BUG_ON_PAGE(!Page##uname(page), page);                       \
        page->page_type |= PG_##lname;                                  \
-}                                                                      \
-static __always_inline void __folio_clear_##fname(struct folio *folio) \
-{                                                                      \
-       VM_BUG_ON_FOLIO(!folio_test_##fname(folio), folio);             \
-       folio->page.page_type |= PG_##lname;                            \
-}                                                                      \
+}
 
 /*
  * PageBuddy() indicates that the page is free and in the buddy system
@@ -1052,6 +1041,37 @@ PAGE_TYPE_OPS(Table, table, pgtable)
  */
 PAGE_TYPE_OPS(Guard, guard, guard)
 
+#ifdef CONFIG_HUGETLB_PAGE
+FOLIO_TYPE_OPS(hugetlb, hugetlb)
+#else
+FOLIO_TEST_FLAG_FALSE(hugetlb)
+#endif
+
+/**
+ * PageHuge - Determine if the page belongs to hugetlbfs
+ * @page: The page to test.
+ *
+ * Context: Any context.
+ * Return: True for hugetlbfs pages, false for anon pages or pages
+ * belonging to other filesystems.
+ */
+static inline bool PageHuge(const struct page *page)
+{
+       return folio_test_hugetlb(page_folio(page));
+}
+
+/*
+ * Check if a page is currently marked HWPoisoned. Note that this check is
+ * best effort only and inherently racy: there is no way to synchronize with
+ * failing hardware.
+ */
+static inline bool is_page_hwpoison(struct page *page)
+{
+       if (PageHWPoison(page))
+               return true;
+       return PageHuge(page) && PageHWPoison(compound_head(page));
+}
+
 extern bool is_free_buddy_page(struct page *page);
 
 PAGEFLAG(Isolated, isolated, PF_ANY);
@@ -1118,7 +1138,7 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page)
  */
 #define PAGE_FLAGS_SECOND                                              \
        (0xffUL /* order */             | 1UL << PG_has_hwpoisoned |    \
-        1UL << PG_hugetlb              | 1UL << PG_large_rmappable)
+        1UL << PG_large_rmappable)
 
 #define PAGE_FLAGS_PRIVATE                             \
        (1UL << PG_private | 1UL << PG_private_2)
index 9b3d36aff431e14f487db75084ed3a68ef1cdf7f..90e241458ef6907e7e29e95a46cbf0e1dacbcc00 100644 (file)
@@ -58,7 +58,6 @@ static inline struct peci_controller *to_peci_controller(void *d)
 /**
  * struct peci_device - PECI device
  * @dev: device object to register PECI device to the device model
- * @controller: manages the bus segment hosting this PECI device
  * @info: PECI device characteristics
  * @info.family: device family
  * @info.model: device model
index 6eb9adaef52beb72442a06c7cd77ed6182f7a14a..76cd1f9f1365306ab45b2832767e400f09e503bc 100644 (file)
@@ -107,7 +107,7 @@ extern void wakeup_sources_read_unlock(int idx);
 extern struct wakeup_source *wakeup_sources_walk_start(void);
 extern struct wakeup_source *wakeup_sources_walk_next(struct wakeup_source *ws);
 extern int device_wakeup_enable(struct device *dev);
-extern int device_wakeup_disable(struct device *dev);
+extern void device_wakeup_disable(struct device *dev);
 extern void device_set_wakeup_capable(struct device *dev, bool capable);
 extern int device_set_wakeup_enable(struct device *dev, bool enable);
 extern void __pm_stay_awake(struct wakeup_source *ws);
@@ -154,10 +154,9 @@ static inline int device_wakeup_enable(struct device *dev)
        return 0;
 }
 
-static inline int device_wakeup_disable(struct device *dev)
+static inline void device_wakeup_disable(struct device *dev)
 {
        dev->power.should_wakeup = false;
-       return 0;
 }
 
 static inline int device_set_wakeup_enable(struct device *dev, bool enable)
@@ -235,11 +234,10 @@ static inline int device_init_wakeup(struct device *dev, bool enable)
        if (enable) {
                device_set_wakeup_capable(dev, true);
                return device_wakeup_enable(dev);
-       } else {
-               device_wakeup_disable(dev);
-               device_set_wakeup_capable(dev, false);
-               return 0;
        }
+       device_wakeup_disable(dev);
+       device_set_wakeup_capable(dev, false);
+       return 0;
 }
 
 #endif /* _LINUX_PM_WAKEUP_H */
index 11db1ec516e272ab030716b6206340b43a44dac8..04ae5ebcb637aa2d3c11184307a68c026753a375 100644 (file)
@@ -18,13 +18,8 @@ struct proc_dir_entry;
 struct notifier_block;
 
 #if defined(CONFIG_PROFILING) && defined(CONFIG_PROC_FS)
-void create_prof_cpu_mask(void);
 int create_proc_profile(void);
 #else
-static inline void create_prof_cpu_mask(void)
-{
-}
-
 static inline int create_proc_profile(void)
 {
        return 0;
index b743241cfb7caa22da0e12098da3ea7dead08a9b..d470303b1bbbbe9d3e468cab99cdb3e72067d66f 100644 (file)
@@ -1230,6 +1230,7 @@ int regmap_multi_reg_write_bypassed(struct regmap *map,
 int regmap_raw_write_async(struct regmap *map, unsigned int reg,
                           const void *val, size_t val_len);
 int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
+int regmap_read_bypassed(struct regmap *map, unsigned int reg, unsigned int *val);
 int regmap_raw_read(struct regmap *map, unsigned int reg,
                    void *val, size_t val_len);
 int regmap_noinc_read(struct regmap *map, unsigned int reg,
@@ -1739,6 +1740,13 @@ static inline int regmap_read(struct regmap *map, unsigned int reg,
        return -EINVAL;
 }
 
+static inline int regmap_read_bypassed(struct regmap *map, unsigned int reg,
+                                      unsigned int *val)
+{
+       WARN_ONCE(1, "regmap API is disabled");
+       return -EINVAL;
+}
+
 static inline int regmap_raw_read(struct regmap *map, unsigned int reg,
                                  void *val, size_t val_len)
 {
index 4660582a33022fc15946a811105318199ccaca42..ed180ca419dad94d6e7db7eae820a26f8dcc5e48 100644 (file)
@@ -320,13 +320,13 @@ devm_regulator_get_exclusive(struct device *dev, const char *id)
 
 static inline int devm_regulator_get_enable(struct device *dev, const char *id)
 {
-       return -ENODEV;
+       return 0;
 }
 
 static inline int devm_regulator_get_enable_optional(struct device *dev,
                                                     const char *id)
 {
-       return -ENODEV;
+       return 0;
 }
 
 static inline struct regulator *__must_check
index a4c15db2f5e5401373e66a1b1f66ffd5e97ae35e..3fb18f7eb73eafecf8101a6e73a141cc4d46a0f9 100644 (file)
@@ -110,8 +110,17 @@ extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
 extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end);
 int shmem_unuse(unsigned int type);
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
 extern bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force,
                          struct mm_struct *mm, unsigned long vm_flags);
+#else
+static __always_inline bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force,
+                                         struct mm_struct *mm, unsigned long vm_flags)
+{
+       return false;
+}
+#endif
+
 #ifdef CONFIG_SHMEM
 extern unsigned long shmem_swap_usage(struct vm_area_struct *vma);
 #else
index e65ec3fd27998a5b82fc2c4597c575125e653056..a509caf823d6188070d17da6c7724f6d07eb0997 100644 (file)
@@ -461,10 +461,12 @@ static inline void sk_psock_put(struct sock *sk, struct sk_psock *psock)
 
 static inline void sk_psock_data_ready(struct sock *sk, struct sk_psock *psock)
 {
+       read_lock_bh(&sk->sk_callback_lock);
        if (psock->saved_data_ready)
                psock->saved_data_ready(sk);
        else
                sk->sk_data_ready(sk);
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static inline void psock_set_prog(struct bpf_prog **pprog,
index 24cd199dd6f3a972f44344eb3994334201145e63..d33bab33099ab0fe4db1a889117307510e1035fa 100644 (file)
@@ -210,7 +210,6 @@ struct svc_rdma_recv_ctxt {
  */
 struct svc_rdma_write_info {
        struct svcxprt_rdma     *wi_rdma;
-       struct list_head        wi_list;
 
        const struct svc_rdma_chunk     *wi_chunk;
 
@@ -239,10 +238,7 @@ struct svc_rdma_send_ctxt {
        struct ib_cqe           sc_cqe;
        struct xdr_buf          sc_hdrbuf;
        struct xdr_stream       sc_stream;
-
-       struct list_head        sc_write_info_list;
        struct svc_rdma_write_info sc_reply_info;
-
        void                    *sc_xprt_buf;
        int                     sc_page_count;
        int                     sc_cur_sge_no;
@@ -274,14 +270,11 @@ extern void svc_rdma_cc_init(struct svcxprt_rdma *rdma,
 extern void svc_rdma_cc_release(struct svcxprt_rdma *rdma,
                                struct svc_rdma_chunk_ctxt *cc,
                                enum dma_data_direction dir);
-extern void svc_rdma_write_chunk_release(struct svcxprt_rdma *rdma,
-                                        struct svc_rdma_send_ctxt *ctxt);
 extern void svc_rdma_reply_chunk_release(struct svcxprt_rdma *rdma,
                                         struct svc_rdma_send_ctxt *ctxt);
-extern int svc_rdma_prepare_write_list(struct svcxprt_rdma *rdma,
-                                      const struct svc_rdma_pcl *write_pcl,
-                                      struct svc_rdma_send_ctxt *sctxt,
-                                      const struct xdr_buf *xdr);
+extern int svc_rdma_send_write_list(struct svcxprt_rdma *rdma,
+                                   const struct svc_rdma_recv_ctxt *rctxt,
+                                   const struct xdr_buf *xdr);
 extern int svc_rdma_prepare_reply_chunk(struct svcxprt_rdma *rdma,
                                        const struct svc_rdma_pcl *write_pcl,
                                        const struct svc_rdma_pcl *reply_pcl,
index 48b700ba1d188a798209d4de4693173bfc6b98af..a5c560a2f8c25867e8e3e53588d551ea3b356feb 100644 (file)
@@ -390,6 +390,35 @@ static inline bool is_migration_entry_dirty(swp_entry_t entry)
 }
 #endif /* CONFIG_MIGRATION */
 
+#ifdef CONFIG_MEMORY_FAILURE
+
+/*
+ * Support for hardware poisoned pages
+ */
+static inline swp_entry_t make_hwpoison_entry(struct page *page)
+{
+       BUG_ON(!PageLocked(page));
+       return swp_entry(SWP_HWPOISON, page_to_pfn(page));
+}
+
+static inline int is_hwpoison_entry(swp_entry_t entry)
+{
+       return swp_type(entry) == SWP_HWPOISON;
+}
+
+#else
+
+static inline swp_entry_t make_hwpoison_entry(struct page *page)
+{
+       return swp_entry(0, 0);
+}
+
+static inline int is_hwpoison_entry(swp_entry_t swp)
+{
+       return 0;
+}
+#endif
+
 typedef unsigned long pte_marker;
 
 #define  PTE_MARKER_UFFD_WP                    BIT(0)
@@ -483,8 +512,9 @@ static inline struct folio *pfn_swap_entry_folio(swp_entry_t entry)
 
 /*
  * A pfn swap entry is a special type of swap entry that always has a pfn stored
- * in the swap offset. They are used to represent unaddressable device memory
- * and to restrict access to a page undergoing migration.
+ * in the swap offset. They can either be used to represent unaddressable device
+ * memory, to restrict access to a page undergoing migration or to represent a
+ * pfn which has been hwpoisoned and unmapped.
  */
 static inline bool is_pfn_swap_entry(swp_entry_t entry)
 {
@@ -492,7 +522,7 @@ static inline bool is_pfn_swap_entry(swp_entry_t entry)
        BUILD_BUG_ON(SWP_TYPE_SHIFT < SWP_PFN_BITS);
 
        return is_migration_entry(entry) || is_device_private_entry(entry) ||
-              is_device_exclusive_entry(entry);
+              is_device_exclusive_entry(entry) || is_hwpoison_entry(entry);
 }
 
 struct page_vma_mapped_walk;
@@ -561,35 +591,6 @@ static inline int is_pmd_migration_entry(pmd_t pmd)
 }
 #endif  /* CONFIG_ARCH_ENABLE_THP_MIGRATION */
 
-#ifdef CONFIG_MEMORY_FAILURE
-
-/*
- * Support for hardware poisoned pages
- */
-static inline swp_entry_t make_hwpoison_entry(struct page *page)
-{
-       BUG_ON(!PageLocked(page));
-       return swp_entry(SWP_HWPOISON, page_to_pfn(page));
-}
-
-static inline int is_hwpoison_entry(swp_entry_t entry)
-{
-       return swp_type(entry) == SWP_HWPOISON;
-}
-
-#else
-
-static inline swp_entry_t make_hwpoison_entry(struct page *page)
-{
-       return swp_entry(0, 0);
-}
-
-static inline int is_hwpoison_entry(swp_entry_t swp)
-{
-       return 0;
-}
-#endif
-
 static inline int non_swap_entry(swp_entry_t entry)
 {
        return swp_type(entry) >= MAX_SWAPFILES;
index 7a5fe17b6bf9c628bc669d82ad16d7cc9abdb88f..d03f746587167e3c26b19b62f6704f15e96abb66 100644 (file)
@@ -62,6 +62,8 @@ struct eventfs_file;
 typedef int (*eventfs_callback)(const char *name, umode_t *mode, void **data,
                                const struct file_operations **fops);
 
+typedef void (*eventfs_release)(const char *name, void *data);
+
 /**
  * struct eventfs_entry - dynamically created eventfs file call back handler
  * @name:      Then name of the dynamic file in an eventfs directory
@@ -72,6 +74,7 @@ typedef int (*eventfs_callback)(const char *name, umode_t *mode, void **data,
 struct eventfs_entry {
        const char                      *name;
        eventfs_callback                callback;
+       eventfs_release                 release;
 };
 
 struct eventfs_inode;
index 17539d08966618bfe4c2f0b41f4893c8951b22fe..e398e1dbd2d365c54874a6f368adacf6734e9f03 100644 (file)
@@ -108,7 +108,7 @@ struct udp_sock {
 #define udp_assign_bit(nr, sk, val)            \
        assign_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags, val)
 
-#define UDP_MAX_SEGMENTS       (1 << 6UL)
+#define UDP_MAX_SEGMENTS       (1 << 7UL)
 
 #define udp_sk(ptr) container_of_const(ptr, struct udp_sock, inet.sk)
 
index 627ea8e2d915984091944cf114c4d46d4631f6f4..3dee0b2721aa402ce020fcbda72250980afc52ad 100644 (file)
@@ -85,6 +85,9 @@ enum unix_socket_lock_class {
        U_LOCK_NORMAL,
        U_LOCK_SECOND,  /* for double locking, see unix_state_double_lock(). */
        U_LOCK_DIAG, /* used while dumping icons, see sk_diag_dump_icons(). */
+       U_LOCK_GC_LISTENER, /* used for listening socket while determining gc
+                            * candidates to close a small race window.
+                            */
 };
 
 static inline void unix_state_lock_nested(struct sock *sk,
index 56fb42df44a3331f3665499f5e81cdcdf2c2f64d..e8f581f3f3ce6d4fe3d0d6db8c8a9688daf4addb 100644 (file)
@@ -738,6 +738,8 @@ struct hci_conn {
        __u8            le_per_adv_data[HCI_MAX_PER_AD_TOT_LEN];
        __u16           le_per_adv_data_len;
        __u16           le_per_adv_data_offset;
+       __u8            le_adv_phy;
+       __u8            le_adv_sec_phy;
        __u8            le_tx_phy;
        __u8            le_rx_phy;
        __s8            rssi;
@@ -1512,7 +1514,7 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
                                     enum conn_reasons conn_reason);
 struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
                                u8 dst_type, bool dst_resolved, u8 sec_level,
-                               u16 conn_timeout, u8 role);
+                               u16 conn_timeout, u8 role, u8 phy, u8 sec_phy);
 void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status);
 struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
                                 u8 sec_level, u8 auth_type,
@@ -1905,6 +1907,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define privacy_mode_capable(dev) (use_ll_privacy(dev) && \
                                   (hdev->commands[39] & 0x04))
 
+#define read_key_size_capable(dev) \
+       ((dev)->commands[20] & 0x10 && \
+        !test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks))
+
 /* Use enhanced synchronous connection if command is supported and its quirk
  * has not been set.
  */
index 50f1e403dbbb3805277d74ff80b504677e9a7aa0..c1d4ca0463a178736d2416e172784e35e333e126 100644 (file)
@@ -87,6 +87,15 @@ struct napi_gro_cb {
 
        /* used to support CHECKSUM_COMPLETE for tunneling protocols */
        __wsum  csum;
+
+       /* L3 offsets */
+       union {
+               struct {
+                       u16 network_offset;
+                       u16 inner_network_offset;
+               };
+               u16 network_offsets[2];
+       };
 };
 
 #define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb)
index 353488ab94a294fd1fb2a985d015f9c8b59d421d..2d7f87bc5324b4823a8f70b960f0545bab8549c4 100644 (file)
@@ -953,6 +953,8 @@ enum mac80211_tx_info_flags {
  *     of their QoS TID or other priority field values.
  * @IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX: first MLO TX, used mostly internally
  *     for sequence number assignment
+ * @IEEE80211_TX_CTRL_SCAN_TX: Indicates that this frame is transmitted
+ *     due to scanning, not in normal operation on the interface.
  * @IEEE80211_TX_CTRL_MLO_LINK: If not @IEEE80211_LINK_UNSPECIFIED, this
  *     frame should be transmitted on the specific link. This really is
  *     only relevant for frames that do not have data present, and is
@@ -973,6 +975,7 @@ enum mac80211_tx_control_flags {
        IEEE80211_TX_CTRL_NO_SEQNO              = BIT(7),
        IEEE80211_TX_CTRL_DONT_REORDER          = BIT(8),
        IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX    = BIT(9),
+       IEEE80211_TX_CTRL_SCAN_TX               = BIT(10),
        IEEE80211_TX_CTRL_MLO_LINK              = 0xf0000000,
 };
 
index dbd22180cc5c3418cfa47261639d3ab7bbf55bee..de216cbc6b059fba9f795f83c6be43f5169c8649 100644 (file)
@@ -321,6 +321,7 @@ struct macsec_context {
  *     for the TX tag
  * @needed_tailroom: number of bytes reserved at the end of the sk_buff for the
  *     TX tag
+ * @rx_uses_md_dst: whether MACsec device offload supports sk_buff md_dst
  */
 struct macsec_ops {
        /* Device wide */
@@ -352,6 +353,7 @@ struct macsec_ops {
                                 struct sk_buff *skb);
        unsigned int needed_headroom;
        unsigned int needed_tailroom;
+       bool rx_uses_md_dst;
 };
 
 void macsec_pn_wrapped(struct macsec_secy *secy, struct macsec_tx_sa *tx_sa);
index a763dd327c6ea95d6b94fda1ea2efd8f1784335f..9abb7ee40d72fc2e7d2ef0ec86ef18df939ddd9c 100644 (file)
@@ -336,7 +336,7 @@ int nf_flow_rule_route_ipv6(struct net *net, struct flow_offload *flow,
 int nf_flow_table_offload_init(void);
 void nf_flow_table_offload_exit(void);
 
-static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
+static inline __be16 __nf_flow_pppoe_proto(const struct sk_buff *skb)
 {
        __be16 proto;
 
@@ -352,6 +352,16 @@ static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
        return 0;
 }
 
+static inline bool nf_flow_pppoe_proto(struct sk_buff *skb, __be16 *inner_proto)
+{
+       if (!pskb_may_pull(skb, PPPOE_SES_HLEN))
+               return false;
+
+       *inner_proto = __nf_flow_pppoe_proto(skb);
+
+       return true;
+}
+
 #define NF_FLOW_TABLE_STAT_INC(net, count) __this_cpu_inc((net)->ft.stat->count)
 #define NF_FLOW_TABLE_STAT_DEC(net, count) __this_cpu_dec((net)->ft.stat->count)
 #define NF_FLOW_TABLE_STAT_INC_ATOMIC(net, count)      \
index e27c28b612e464ca41c9f07e213d48bf84f11bf6..3f1ed467f951f6342d9ee8da6b576cf8c787af2d 100644 (file)
@@ -307,9 +307,23 @@ static inline void *nft_elem_priv_cast(const struct nft_elem_priv *priv)
        return (void *)priv;
 }
 
+
+/**
+ * enum nft_iter_type - nftables set iterator type
+ *
+ * @NFT_ITER_READ: read-only iteration over set elements
+ * @NFT_ITER_UPDATE: iteration under mutex to update set element state
+ */
+enum nft_iter_type {
+       NFT_ITER_UNSPEC,
+       NFT_ITER_READ,
+       NFT_ITER_UPDATE,
+};
+
 struct nft_set;
 struct nft_set_iter {
        u8              genmask;
+       enum nft_iter_type type:8;
        unsigned int    count;
        unsigned int    skip;
        int             err;
index cefe0c4bdae34c91868c22731a3b666f8e16e996..41ca14e81d55f926dc4002e820d7e027f4729021 100644 (file)
@@ -117,6 +117,7 @@ struct Qdisc {
        struct qdisc_skb_head   q;
        struct gnet_stats_basic_sync bstats;
        struct gnet_stats_queue qstats;
+       int                     owner;
        unsigned long           state;
        unsigned long           state2; /* must be written under qdisc spinlock */
        struct Qdisc            *next_sched;
index f57bfd8a2ad2deaedf3f351325ab9336ae040504..b4b553df7870c0290ae632c51828ad7161ba332d 100644 (file)
@@ -1410,32 +1410,34 @@ sk_memory_allocated(const struct sock *sk)
 #define SK_MEMORY_PCPU_RESERVE (1 << (20 - PAGE_SHIFT))
 extern int sysctl_mem_pcpu_rsv;
 
+static inline void proto_memory_pcpu_drain(struct proto *proto)
+{
+       int val = this_cpu_xchg(*proto->per_cpu_fw_alloc, 0);
+
+       if (val)
+               atomic_long_add(val, proto->memory_allocated);
+}
+
 static inline void
-sk_memory_allocated_add(struct sock *sk, int amt)
+sk_memory_allocated_add(const struct sock *sk, int val)
 {
-       int local_reserve;
+       struct proto *proto = sk->sk_prot;
 
-       preempt_disable();
-       local_reserve = __this_cpu_add_return(*sk->sk_prot->per_cpu_fw_alloc, amt);
-       if (local_reserve >= READ_ONCE(sysctl_mem_pcpu_rsv)) {
-               __this_cpu_sub(*sk->sk_prot->per_cpu_fw_alloc, local_reserve);
-               atomic_long_add(local_reserve, sk->sk_prot->memory_allocated);
-       }
-       preempt_enable();
+       val = this_cpu_add_return(*proto->per_cpu_fw_alloc, val);
+
+       if (unlikely(val >= READ_ONCE(sysctl_mem_pcpu_rsv)))
+               proto_memory_pcpu_drain(proto);
 }
 
 static inline void
-sk_memory_allocated_sub(struct sock *sk, int amt)
+sk_memory_allocated_sub(const struct sock *sk, int val)
 {
-       int local_reserve;
+       struct proto *proto = sk->sk_prot;
 
-       preempt_disable();
-       local_reserve = __this_cpu_sub_return(*sk->sk_prot->per_cpu_fw_alloc, amt);
-       if (local_reserve <= -READ_ONCE(sysctl_mem_pcpu_rsv)) {
-               __this_cpu_sub(*sk->sk_prot->per_cpu_fw_alloc, local_reserve);
-               atomic_long_add(local_reserve, sk->sk_prot->memory_allocated);
-       }
-       preempt_enable();
+       val = this_cpu_sub_return(*proto->per_cpu_fw_alloc, val);
+
+       if (unlikely(val <= -READ_ONCE(sysctl_mem_pcpu_rsv)))
+               proto_memory_pcpu_drain(proto);
 }
 
 #define SK_ALLOC_PERCPU_COUNTER_BATCH 16
index 340ad43971e4711d8091a6397bb5cf3c3c4ef0fd..33f657d3c0510a0bd9e9899bc2530f9d035ce366 100644 (file)
@@ -111,7 +111,8 @@ struct tls_strparser {
        u32 stopped : 1;
        u32 copy_mode : 1;
        u32 mixed_decrypted : 1;
-       u32 msg_ready : 1;
+
+       bool msg_ready;
 
        struct strp_msg stm;
 
index e0629699b56338a76b69616dcc2a79dece2e51f4..1a3c6f66f6205597cb46b3c7cc826802fc35c740 100644 (file)
@@ -267,6 +267,7 @@ struct cs35l56_base {
        bool fw_patched;
        bool secured;
        bool can_hibernate;
+       bool fw_owns_asp1;
        bool cal_data_valid;
        s8 cal_index;
        struct cirrus_amp_cal_data cal_data;
@@ -283,6 +284,7 @@ extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC];
 extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC];
 
 int cs35l56_set_patch(struct cs35l56_base *cs35l56_base);
+int cs35l56_init_asp1_regs_for_driver_control(struct cs35l56_base *cs35l56_base);
 int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base);
 int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command);
 int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base);
index 1af9e68193920d062f3c9cce40eba41dc8d74292..234b5baea69c8e6154c3c048fe002bf99337e245 100644 (file)
@@ -1684,8 +1684,8 @@ struct snd_emu1010 {
        unsigned int clock_fallback;
        unsigned int optical_in; /* 0:SPDIF, 1:ADAT */
        unsigned int optical_out; /* 0:SPDIF, 1:ADAT */
-       struct work_struct firmware_work;
-       struct work_struct clock_work;
+       struct work_struct work;
+       struct mutex lock;
 };
 
 struct snd_emu10k1 {
@@ -1834,6 +1834,9 @@ unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg,
 void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data);
 int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data);
 int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
+static inline void snd_emu1010_fpga_lock(struct snd_emu10k1 *emu) { mutex_lock(&emu->emu1010.lock); };
+static inline void snd_emu1010_fpga_unlock(struct snd_emu10k1 *emu) { mutex_unlock(&emu->emu1010.lock); };
+void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value);
 void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
 void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value);
 void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src);
index d801409b33cfec29c84150173908c9522b4cfa60..d55e53ac91bd2cbb3cc24836a96a4d38af752c9d 100644 (file)
@@ -135,6 +135,7 @@ IF_HAVE_PG_ARCH_X(arch_3)
 #define DEF_PAGETYPE_NAME(_name) { PG_##_name, __stringify(_name) }
 
 #define __def_pagetype_names                                           \
+       DEF_PAGETYPE_NAME(hugetlb),                                     \
        DEF_PAGETYPE_NAME(offline),                                     \
        DEF_PAGETYPE_NAME(guard),                                       \
        DEF_PAGETYPE_NAME(table),                                       \
index ba2d96a1bc2f94703945c5f79294a66af1fe8fd4..f50fcafc69de20b8b20a53a45f29b23f4259a65e 100644 (file)
@@ -609,7 +609,7 @@ TRACE_EVENT(rpcgss_context,
                __field(unsigned int, timeout)
                __field(u32, window_size)
                __field(int, len)
-               __string(acceptor, data)
+               __string_len(acceptor, data, len)
        ),
 
        TP_fast_assign(
@@ -618,7 +618,7 @@ TRACE_EVENT(rpcgss_context,
                __entry->timeout = timeout;
                __entry->window_size = window_size;
                __entry->len = len;
-               strncpy(__get_str(acceptor), data, len);
+               __assign_str(acceptor, data);
        ),
 
        TP_printk("win_size=%u expiry=%lu now=%lu timeout=%u acceptor=%.*s",
index d87410a8443aaeadd86966e86a8bec59c8fd9f87..af024d90453ddc5376892b13efd8e6c51043e97e 100644 (file)
@@ -77,11 +77,6 @@ struct drm_etnaviv_timespec {
 #define ETNAVIV_PARAM_GPU_PRODUCT_ID                0x1c
 #define ETNAVIV_PARAM_GPU_CUSTOMER_ID               0x1d
 #define ETNAVIV_PARAM_GPU_ECO_ID                    0x1e
-#define ETNAVIV_PARAM_GPU_NN_CORE_COUNT             0x1f
-#define ETNAVIV_PARAM_GPU_NN_MAD_PER_CORE           0x20
-#define ETNAVIV_PARAM_GPU_TP_CORE_COUNT             0x21
-#define ETNAVIV_PARAM_GPU_ON_CHIP_SRAM_SIZE         0x22
-#define ETNAVIV_PARAM_GPU_AXI_SRAM_SIZE             0x23
 
 #define ETNA_MAX_PIPES 4
 
index 43c51698195ceb0619e5b2787428be675b007a7f..842bf1201ac4142813d2ea3a90e8f34e20ea5fd5 100644 (file)
@@ -57,7 +57,7 @@ enum vdpa_attr {
        VDPA_ATTR_DEV_FEATURES,                 /* u64 */
 
        VDPA_ATTR_DEV_BLK_CFG_CAPACITY,         /* u64 */
-       VDPA_ATTR_DEV_BLK_CFG_SEG_SIZE,         /* u32 */
+       VDPA_ATTR_DEV_BLK_CFG_SIZE_MAX,         /* u32 */
        VDPA_ATTR_DEV_BLK_CFG_BLK_SIZE,         /* u32 */
        VDPA_ATTR_DEV_BLK_CFG_SEG_MAX,          /* u32 */
        VDPA_ATTR_DEV_BLK_CFG_NUM_QUEUES,       /* u16 */
@@ -70,8 +70,8 @@ enum vdpa_attr {
        VDPA_ATTR_DEV_BLK_CFG_DISCARD_SEC_ALIGN,/* u32 */
        VDPA_ATTR_DEV_BLK_CFG_MAX_WRITE_ZEROES_SEC,     /* u32 */
        VDPA_ATTR_DEV_BLK_CFG_MAX_WRITE_ZEROES_SEG,     /* u32 */
-       VDPA_ATTR_DEV_BLK_CFG_READ_ONLY,                /* u8 */
-       VDPA_ATTR_DEV_BLK_CFG_FLUSH,            /* u8 */
+       VDPA_ATTR_DEV_BLK_READ_ONLY,            /* u8 */
+       VDPA_ATTR_DEV_BLK_FLUSH,                /* u8 */
 
        /* new attributes must be added above here */
        VDPA_ATTR_MAX,
index aa02aec6aa7d29432f1974003900fce14bf14452..664bedb9a71fbe97c9726c1397d5c8b2043d1da4 100644 (file)
@@ -1899,11 +1899,11 @@ config RUST
        bool "Rust support"
        depends on HAVE_RUST
        depends on RUST_IS_AVAILABLE
+       depends on !CFI_CLANG
        depends on !MODVERSIONS
        depends on !GCC_PLUGINS
        depends on !RANDSTRUCT
        depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE
-       select CONSTRUCTORS
        help
          Enables Rust support in the kernel.
 
index 881f6230ee59e9675eb98b62adf761ee74823a16..5dcf5274c09c7ae60232051569bd24651a8379af 100644 (file)
@@ -636,6 +636,8 @@ static void __init setup_command_line(char *command_line)
        if (!saved_command_line)
                panic("%s: Failed to allocate %zu bytes\n", __func__, len + ilen);
 
+       len = xlen + strlen(command_line) + 1;
+
        static_command_line = memblock_alloc(len, SMP_CACHE_BYTES);
        if (!static_command_line)
                panic("%s: Failed to allocate %zu bytes\n", __func__, len);
index c5a9fcd2d622819cc1f5b0f5cfd772514ee5f423..29b2cd00df2ccf2b991b9b78f4514b76c87ee354 100644 (file)
@@ -19,7 +19,7 @@ int main(void)
        DEFINE(NR_PAGEFLAGS, __NR_PAGEFLAGS);
        DEFINE(MAX_NR_ZONES, __MAX_NR_ZONES);
 #ifdef CONFIG_SMP
-       DEFINE(NR_CPUS_BITS, bits_per(CONFIG_NR_CPUS));
+       DEFINE(NR_CPUS_BITS, order_base_2(CONFIG_NR_CPUS));
 #endif
        DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t));
 #ifdef CONFIG_LRU_GEN
index 696bc55de8e82ea9358ede9c222b4927871e60be..1ea5ce5bb59933ac4449567c52f1981c8df8a139 100644 (file)
@@ -2942,6 +2942,15 @@ bool __weak bpf_jit_supports_arena(void)
        return false;
 }
 
+u64 __weak bpf_arch_uaddress_limit(void)
+{
+#if defined(CONFIG_64BIT) && defined(CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE)
+       return TASK_SIZE;
+#else
+       return 0;
+#endif
+}
+
 /* Return TRUE if the JIT backend satisfies the following two conditions:
  * 1) JIT backend supports atomic_xchg() on pointer-sized words.
  * 2) Under the specific arch, the implementation of xchg() is the same
index 98188379d5c77d79d3a5e764659ed4426f931d14..cb7ad1f795e18b1abec57dc5e40f2d852416bb04 100644 (file)
@@ -18289,8 +18289,7 @@ static int resolve_pseudo_ldimm64(struct bpf_verifier_env *env)
                        f = fdget(fd);
                        map = __bpf_map_get(f);
                        if (IS_ERR(map)) {
-                               verbose(env, "fd %d is not pointing to valid bpf_map\n",
-                                       insn[0].imm);
+                               verbose(env, "fd %d is not pointing to valid bpf_map\n", fd);
                                return PTR_ERR(map);
                        }
 
@@ -19676,6 +19675,36 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
                        goto next_insn;
                }
 
+               /* Make it impossible to de-reference a userspace address */
+               if (BPF_CLASS(insn->code) == BPF_LDX &&
+                   (BPF_MODE(insn->code) == BPF_PROBE_MEM ||
+                    BPF_MODE(insn->code) == BPF_PROBE_MEMSX)) {
+                       struct bpf_insn *patch = &insn_buf[0];
+                       u64 uaddress_limit = bpf_arch_uaddress_limit();
+
+                       if (!uaddress_limit)
+                               goto next_insn;
+
+                       *patch++ = BPF_MOV64_REG(BPF_REG_AX, insn->src_reg);
+                       if (insn->off)
+                               *patch++ = BPF_ALU64_IMM(BPF_ADD, BPF_REG_AX, insn->off);
+                       *patch++ = BPF_ALU64_IMM(BPF_RSH, BPF_REG_AX, 32);
+                       *patch++ = BPF_JMP_IMM(BPF_JLE, BPF_REG_AX, uaddress_limit >> 32, 2);
+                       *patch++ = *insn;
+                       *patch++ = BPF_JMP_IMM(BPF_JA, 0, 0, 1);
+                       *patch++ = BPF_MOV64_IMM(insn->dst_reg, 0);
+
+                       cnt = patch - insn_buf;
+                       new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
+                       if (!new_prog)
+                               return -ENOMEM;
+
+                       delta    += cnt - 1;
+                       env->prog = prog = new_prog;
+                       insn      = new_prog->insnsi + i + delta;
+                       goto next_insn;
+               }
+
                /* Implement LD_ABS and LD_IND with a rewrite, if supported by the program type. */
                if (BPF_CLASS(insn->code) == BPF_LD &&
                    (BPF_MODE(insn->code) == BPF_ABS ||
index 7a5bbfc024b7d0ee0c376f71474a0cca042c0824..4b4cfcba319013e8bc715e3cbfcd285088bf977c 100644 (file)
@@ -39,11 +39,12 @@ CONFIG_UBSAN=y
 CONFIG_UBSAN_TRAP=y
 CONFIG_UBSAN_BOUNDS=y
 # CONFIG_UBSAN_SHIFT is not set
-# CONFIG_UBSAN_DIV_ZERO
-# CONFIG_UBSAN_UNREACHABLE
-# CONFIG_UBSAN_BOOL
-# CONFIG_UBSAN_ENUM
-# CONFIG_UBSAN_ALIGNMENT
+# CONFIG_UBSAN_DIV_ZERO is not set
+# CONFIG_UBSAN_UNREACHABLE is not set
+# CONFIG_UBSAN_SIGNED_WRAP is not set
+# CONFIG_UBSAN_BOOL is not set
+# CONFIG_UBSAN_ENUM is not set
+# CONFIG_UBSAN_ALIGNMENT is not set
 
 # Sampling-based heap out-of-bounds and use-after-free detection.
 CONFIG_KFENCE=y
index 07ad53b7f11952080e890ed91f99f3e762bf984d..63447eb85dab6bd0fa2ab23c25bffdf788a2b9c1 100644 (file)
@@ -3196,6 +3196,7 @@ void __init boot_cpu_hotplug_init(void)
        this_cpu_write(cpuhp_state.target, CPUHP_ONLINE);
 }
 
+#ifdef CONFIG_CPU_MITIGATIONS
 /*
  * These are used for a global "mitigations=" cmdline option for toggling
  * optional CPU mitigations.
@@ -3206,9 +3207,7 @@ enum cpu_mitigations {
        CPU_MITIGATIONS_AUTO_NOSMT,
 };
 
-static enum cpu_mitigations cpu_mitigations __ro_after_init =
-       IS_ENABLED(CONFIG_SPECULATION_MITIGATIONS) ? CPU_MITIGATIONS_AUTO :
-                                                    CPU_MITIGATIONS_OFF;
+static enum cpu_mitigations cpu_mitigations __ro_after_init = CPU_MITIGATIONS_AUTO;
 
 static int __init mitigations_parse_cmdline(char *arg)
 {
@@ -3224,7 +3223,6 @@ static int __init mitigations_parse_cmdline(char *arg)
 
        return 0;
 }
-early_param("mitigations", mitigations_parse_cmdline);
 
 /* mitigations=off */
 bool cpu_mitigations_off(void)
@@ -3239,3 +3237,11 @@ bool cpu_mitigations_auto_nosmt(void)
        return cpu_mitigations == CPU_MITIGATIONS_AUTO_NOSMT;
 }
 EXPORT_SYMBOL_GPL(cpu_mitigations_auto_nosmt);
+#else
+static int __init mitigations_parse_cmdline(char *arg)
+{
+       pr_crit("Kernel compiled without mitigations, ignoring 'mitigations'; system may still be vulnerable\n");
+       return 0;
+}
+#endif
+early_param("mitigations", mitigations_parse_cmdline);
index a5e0dfc44d24e22641e72bb0362511a33b23a1fd..0de66f0ff43aba1f64505d70b86d9faac8bc43ff 100644 (file)
@@ -1798,6 +1798,7 @@ static int rmem_swiotlb_device_init(struct reserved_mem *rmem,
                mem->for_alloc = true;
 #ifdef CONFIG_SWIOTLB_DYNAMIC
                spin_lock_init(&mem->lock);
+               INIT_LIST_HEAD_RCU(&mem->pools);
 #endif
                add_mem_pool(mem, pool);
 
index 39a5046c2f0bf49e1bcade15c4c3c5574742b09d..aebb3e6c96dc62e5818ce16e31779868ea669067 100644 (file)
@@ -714,6 +714,23 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
                } else if (anon_vma_fork(tmp, mpnt))
                        goto fail_nomem_anon_vma_fork;
                vm_flags_clear(tmp, VM_LOCKED_MASK);
+               /*
+                * Copy/update hugetlb private vma information.
+                */
+               if (is_vm_hugetlb_page(tmp))
+                       hugetlb_dup_vma_private(tmp);
+
+               /*
+                * Link the vma into the MT. After using __mt_dup(), memory
+                * allocation is not necessary here, so it cannot fail.
+                */
+               vma_iter_bulk_store(&vmi, tmp);
+
+               mm->map_count++;
+
+               if (tmp->vm_ops && tmp->vm_ops->open)
+                       tmp->vm_ops->open(tmp);
+
                file = tmp->vm_file;
                if (file) {
                        struct address_space *mapping = file->f_mapping;
@@ -730,25 +747,9 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
                        i_mmap_unlock_write(mapping);
                }
 
-               /*
-                * Copy/update hugetlb private vma information.
-                */
-               if (is_vm_hugetlb_page(tmp))
-                       hugetlb_dup_vma_private(tmp);
-
-               /*
-                * Link the vma into the MT. After using __mt_dup(), memory
-                * allocation is not necessary here, so it cannot fail.
-                */
-               vma_iter_bulk_store(&vmi, tmp);
-
-               mm->map_count++;
                if (!(tmp->vm_flags & VM_WIPEONFORK))
                        retval = copy_page_range(tmp, mpnt);
 
-               if (tmp->vm_ops && tmp->vm_ops->open)
-                       tmp->vm_ops->open(tmp);
-
                if (retval) {
                        mpnt = vma_next(&vmi);
                        goto loop_out;
index 43b1a82e800c975a2de1e344ade85c3506c8b614..0a213f69a9e4ac0be17020ffb18d7456b7105762 100644 (file)
@@ -1361,7 +1361,7 @@ static int __init resume_setup(char *str)
        if (noresume)
                return 1;
 
-       strncpy(resume_file, str, 255);
+       strscpy(resume_file, str);
        return 1;
 }
 
index 8a77769bc4b4cbb655244fd163fc72a860b4bcdd..2b775cc5c28f96cebe33e6d9c55a001d0debd6ce 100644 (file)
@@ -344,49 +344,6 @@ void profile_tick(int type)
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 
-static int prof_cpu_mask_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%*pb\n", cpumask_pr_args(prof_cpu_mask));
-       return 0;
-}
-
-static int prof_cpu_mask_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, prof_cpu_mask_proc_show, NULL);
-}
-
-static ssize_t prof_cpu_mask_proc_write(struct file *file,
-       const char __user *buffer, size_t count, loff_t *pos)
-{
-       cpumask_var_t new_value;
-       int err;
-
-       if (!zalloc_cpumask_var(&new_value, GFP_KERNEL))
-               return -ENOMEM;
-
-       err = cpumask_parse_user(buffer, count, new_value);
-       if (!err) {
-               cpumask_copy(prof_cpu_mask, new_value);
-               err = count;
-       }
-       free_cpumask_var(new_value);
-       return err;
-}
-
-static const struct proc_ops prof_cpu_mask_proc_ops = {
-       .proc_open      = prof_cpu_mask_proc_open,
-       .proc_read      = seq_read,
-       .proc_lseek     = seq_lseek,
-       .proc_release   = single_release,
-       .proc_write     = prof_cpu_mask_proc_write,
-};
-
-void create_prof_cpu_mask(void)
-{
-       /* create /proc/irq/prof_cpu_mask */
-       proc_create("irq/prof_cpu_mask", 0600, NULL, &prof_cpu_mask_proc_ops);
-}
-
 /*
  * This function accesses profiling information. The returned data is
  * binary: the sampling step and the actual contents of the profile
index 03be0d1330a6b22336c91cd4cfeae7fd82838692..c62805dbd6088b3bd63ac07766b92443f35f0e36 100644 (file)
@@ -696,15 +696,21 @@ u64 avg_vruntime(struct cfs_rq *cfs_rq)
  *
  * XXX could add max_slice to the augmented data to track this.
  */
-static void update_entity_lag(struct cfs_rq *cfs_rq, struct sched_entity *se)
+static s64 entity_lag(u64 avruntime, struct sched_entity *se)
 {
-       s64 lag, limit;
+       s64 vlag, limit;
+
+       vlag = avruntime - se->vruntime;
+       limit = calc_delta_fair(max_t(u64, 2*se->slice, TICK_NSEC), se);
 
+       return clamp(vlag, -limit, limit);
+}
+
+static void update_entity_lag(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
        SCHED_WARN_ON(!se->on_rq);
-       lag = avg_vruntime(cfs_rq) - se->vruntime;
 
-       limit = calc_delta_fair(max_t(u64, 2*se->slice, TICK_NSEC), se);
-       se->vlag = clamp(lag, -limit, limit);
+       se->vlag = entity_lag(avg_vruntime(cfs_rq), se);
 }
 
 /*
@@ -3676,11 +3682,10 @@ static inline void
 dequeue_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se) { }
 #endif
 
-static void reweight_eevdf(struct cfs_rq *cfs_rq, struct sched_entity *se,
+static void reweight_eevdf(struct sched_entity *se, u64 avruntime,
                           unsigned long weight)
 {
        unsigned long old_weight = se->load.weight;
-       u64 avruntime = avg_vruntime(cfs_rq);
        s64 vlag, vslice;
 
        /*
@@ -3761,7 +3766,7 @@ static void reweight_eevdf(struct cfs_rq *cfs_rq, struct sched_entity *se,
         *         = V  - vl'
         */
        if (avruntime != se->vruntime) {
-               vlag = (s64)(avruntime - se->vruntime);
+               vlag = entity_lag(avruntime, se);
                vlag = div_s64(vlag * old_weight, weight);
                se->vruntime = avruntime - vlag;
        }
@@ -3787,25 +3792,26 @@ static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
                            unsigned long weight)
 {
        bool curr = cfs_rq->curr == se;
+       u64 avruntime;
 
        if (se->on_rq) {
                /* commit outstanding execution time */
-               if (curr)
-                       update_curr(cfs_rq);
-               else
+               update_curr(cfs_rq);
+               avruntime = avg_vruntime(cfs_rq);
+               if (!curr)
                        __dequeue_entity(cfs_rq, se);
                update_load_sub(&cfs_rq->load, se->load.weight);
        }
        dequeue_load_avg(cfs_rq, se);
 
-       if (!se->on_rq) {
+       if (se->on_rq) {
+               reweight_eevdf(se, avruntime, weight);
+       } else {
                /*
                 * Because we keep se->vlag = V - v_i, while: lag_i = w_i*(V - v_i),
                 * we need to scale se->vlag when w_i changes.
                 */
                se->vlag = div_s64(se->vlag * se->load.weight, weight);
-       } else {
-               reweight_eevdf(cfs_rq, se, weight);
        }
 
        update_load_set(&se->load, weight);
index 373d42c707bc5d65d70c18d66e0ffd1621d33f5b..5891e715f00d028b0d2f4fd157e99f319b899a1d 100644 (file)
@@ -46,7 +46,16 @@ int housekeeping_any_cpu(enum hk_type type)
                        if (cpu < nr_cpu_ids)
                                return cpu;
 
-                       return cpumask_any_and(housekeeping.cpumasks[type], cpu_online_mask);
+                       cpu = cpumask_any_and(housekeeping.cpumasks[type], cpu_online_mask);
+                       if (likely(cpu < nr_cpu_ids))
+                               return cpu;
+                       /*
+                        * Unless we have another problem this can only happen
+                        * at boot time before start_secondary() brings the 1st
+                        * housekeeping CPU up.
+                        */
+                       WARN_ON_ONCE(system_state == SYSTEM_RUNNING ||
+                                    type != HK_TYPE_TIMER);
                }
        }
        return smp_processor_id();
@@ -109,6 +118,7 @@ static void __init housekeeping_setup_type(enum hk_type type,
 static int __init housekeeping_setup(char *str, unsigned long flags)
 {
        cpumask_var_t non_housekeeping_mask, housekeeping_staging;
+       unsigned int first_cpu;
        int err = 0;
 
        if ((flags & HK_FLAG_TICK) && !(housekeeping.flags & HK_FLAG_TICK)) {
@@ -129,7 +139,8 @@ static int __init housekeeping_setup(char *str, unsigned long flags)
        cpumask_andnot(housekeeping_staging,
                       cpu_possible_mask, non_housekeeping_mask);
 
-       if (!cpumask_intersects(cpu_present_mask, housekeeping_staging)) {
+       first_cpu = cpumask_first_and(cpu_present_mask, housekeeping_staging);
+       if (first_cpu >= nr_cpu_ids || first_cpu >= setup_max_cpus) {
                __cpumask_set_cpu(smp_processor_id(), housekeeping_staging);
                __cpumask_clear_cpu(smp_processor_id(), non_housekeeping_mask);
                if (!housekeeping.flags) {
@@ -138,6 +149,9 @@ static int __init housekeeping_setup(char *str, unsigned long flags)
                }
        }
 
+       if (cpumask_empty(non_housekeeping_mask))
+               goto free_housekeeping_staging;
+
        if (!housekeeping.flags) {
                /* First setup call ("nohz_full=" or "isolcpus=") */
                enum hk_type type;
index d2242679239ec5ad49152400350882d7d7b9819c..ae50f212775e5c529be68b440d16258c9f2d1d10 100644 (file)
@@ -79,6 +79,8 @@
 # include <asm/paravirt_api_clock.h>
 #endif
 
+#include <asm/barrier.h>
+
 #include "cpupri.h"
 #include "cpudeadline.h"
 
@@ -3445,13 +3447,19 @@ static inline void switch_mm_cid(struct rq *rq,
                 * between rq->curr store and load of {prev,next}->mm->pcpu_cid[cpu].
                 * Provide it here.
                 */
-               if (!prev->mm)                          // from kernel
+               if (!prev->mm) {                        // from kernel
                        smp_mb();
-               /*
-                * user -> user transition guarantees a memory barrier through
-                * switch_mm() when current->mm changes. If current->mm is
-                * unchanged, no barrier is needed.
-                */
+               } else {                                // from user
+                       /*
+                        * user->user transition relies on an implicit
+                        * memory barrier in switch_mm() when
+                        * current->mm changes. If the architecture
+                        * switch_mm() does not have an implicit memory
+                        * barrier, it is emitted here.  If current->mm
+                        * is unchanged, no barrier is needed.
+                        */
+                       smp_mb__after_switch_mm();
+               }
        }
        if (prev->mm_cid_active) {
                mm_cid_snapshot_time(rq, prev->mm);
index b315b21fb28cd281fc38d1a8a00ed9f9527e2f53..02582017759a2ce3bfb42faf4be904a7b432595b 100644 (file)
@@ -508,7 +508,7 @@ static inline bool lockdep_softirq_start(void) { return false; }
 static inline void lockdep_softirq_end(bool in_hardirq) { }
 #endif
 
-asmlinkage __visible void __softirq_entry __do_softirq(void)
+static void handle_softirqs(bool ksirqd)
 {
        unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
        unsigned long old_flags = current->flags;
@@ -563,8 +563,7 @@ restart:
                pending >>= softirq_bit;
        }
 
-       if (!IS_ENABLED(CONFIG_PREEMPT_RT) &&
-           __this_cpu_read(ksoftirqd) == current)
+       if (!IS_ENABLED(CONFIG_PREEMPT_RT) && ksirqd)
                rcu_softirq_qs();
 
        local_irq_disable();
@@ -584,6 +583,11 @@ restart:
        current_restore_flags(old_flags, PF_MEMALLOC);
 }
 
+asmlinkage __visible void __softirq_entry __do_softirq(void)
+{
+       handle_softirqs(false);
+}
+
 /**
  * irq_enter_rcu - Enter an interrupt context with RCU watching
  */
@@ -921,7 +925,7 @@ static void run_ksoftirqd(unsigned int cpu)
                 * We can safely run softirq on inline stack, as we are not deep
                 * in the task stack here.
                 */
-               __do_softirq();
+               handle_softirqs(true);
                ksoftirqd_run_end();
                cond_resched();
                return;
index 52f75c36bbca4922bec786815bb70ff409f62a61..6ef29eba90ceb7e06774171d79c7ea244ecaa72a 100644 (file)
@@ -2552,6 +2552,14 @@ static int event_callback(const char *name, umode_t *mode, void **data,
        return 0;
 }
 
+/* The file is incremented on creation and freeing the enable file decrements it */
+static void event_release(const char *name, void *data)
+{
+       struct trace_event_file *file = data;
+
+       event_file_put(file);
+}
+
 static int
 event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file)
 {
@@ -2566,6 +2574,7 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file)
                {
                        .name           = "enable",
                        .callback       = event_callback,
+                       .release        = event_release,
                },
                {
                        .name           = "filter",
@@ -2634,6 +2643,9 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file)
                return ret;
        }
 
+       /* Gets decremented on freeing of the "enable" file */
+       event_file_get(file);
+
        return 0;
 }
 
index dfe3ee6035ecc74da70ebd8104d23f1ef2a25cde..42bc0f3622263b60618fbc8fd39f2f3beedf44a3 100644 (file)
@@ -1466,7 +1466,7 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
                parg->fmt = kmalloc(len, GFP_KERNEL);
                if (!parg->fmt) {
                        ret = -ENOMEM;
-                       goto out;
+                       goto fail;
                }
                snprintf(parg->fmt, len, "%s[%d]", parg->type->fmttype,
                         parg->count);
index f95516cd45bbe29661adc4da4c530c813ad209fe..23c125c2e2436c935a6e35b256d81866777ef35e 100644 (file)
@@ -205,11 +205,10 @@ static int __init crash_save_vmcoreinfo_init(void)
        VMCOREINFO_NUMBER(PG_head_mask);
 #define PAGE_BUDDY_MAPCOUNT_VALUE      (~PG_buddy)
        VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE);
-#ifdef CONFIG_HUGETLB_PAGE
-       VMCOREINFO_NUMBER(PG_hugetlb);
+#define PAGE_HUGETLB_MAPCOUNT_VALUE    (~PG_hugetlb)
+       VMCOREINFO_NUMBER(PAGE_HUGETLB_MAPCOUNT_VALUE);
 #define PAGE_OFFLINE_MAPCOUNT_VALUE    (~PG_offline)
        VMCOREINFO_NUMBER(PAGE_OFFLINE_MAPCOUNT_VALUE);
-#endif
 
 #ifdef CONFIG_KALLSYMS
        VMCOREINFO_SYMBOL(kallsyms_names);
index 0066c8f6c15442641889c87995410ac82d078423..d2dbe099286b95ca5f0b745e577af0e6ed297062 100644 (file)
@@ -1277,8 +1277,12 @@ static bool kick_pool(struct worker_pool *pool)
            !cpumask_test_cpu(p->wake_cpu, pool->attrs->__pod_cpumask)) {
                struct work_struct *work = list_first_entry(&pool->worklist,
                                                struct work_struct, entry);
-               p->wake_cpu = cpumask_any_distribute(pool->attrs->__pod_cpumask);
-               get_work_pwq(work)->stats[PWQ_STAT_REPATRIATED]++;
+               int wake_cpu = cpumask_any_and_distribute(pool->attrs->__pod_cpumask,
+                                                         cpu_online_mask);
+               if (wake_cpu < nr_cpu_ids) {
+                       p->wake_cpu = wake_cpu;
+                       get_work_pwq(work)->stats[PWQ_STAT_REPATRIATED]++;
+               }
        }
 #endif
        wake_up_process(p);
@@ -1594,6 +1598,15 @@ static void wq_update_node_max_active(struct workqueue_struct *wq, int off_cpu)
        if (off_cpu >= 0)
                total_cpus--;
 
+       /* If all CPUs of the wq get offline, use the default values */
+       if (unlikely(!total_cpus)) {
+               for_each_node(node)
+                       wq_node_nr_active(wq, node)->max = min_active;
+
+               wq_node_nr_active(wq, NUMA_NO_NODE)->max = max_active;
+               return;
+       }
+
        for_each_node(node) {
                int node_cpus;
 
@@ -1606,7 +1619,7 @@ static void wq_update_node_max_active(struct workqueue_struct *wq, int off_cpu)
                              min_active, max_active);
        }
 
-       wq_node_nr_active(wq, NUMA_NO_NODE)->max = min_active;
+       wq_node_nr_active(wq, NUMA_NO_NODE)->max = max_active;
 }
 
 /**
index c63a5fbf1f1c2b45b67603886ef9e6f07510f61d..291185f54ee4c217d04b8040b339dc1ad47f9cf6 100644 (file)
@@ -375,7 +375,7 @@ config DEBUG_INFO_SPLIT
          Incompatible with older versions of ccache.
 
 config DEBUG_INFO_BTF
-       bool "Generate BTF typeinfo"
+       bool "Generate BTF type information"
        depends on !DEBUG_INFO_SPLIT && !DEBUG_INFO_REDUCED
        depends on !GCC_PLUGIN_RANDSTRUCT || COMPILE_TEST
        depends on BPF_SYSCALL
@@ -408,7 +408,8 @@ config PAHOLE_HAS_LANG_EXCLUDE
          using DEBUG_INFO_BTF_MODULES.
 
 config DEBUG_INFO_BTF_MODULES
-       def_bool y
+       bool "Generate BTF type information for kernel modules"
+       default y
        depends on DEBUG_INFO_BTF && MODULES && PAHOLE_HAS_SPLIT_BTF
        help
          Generate compact split BTF type information for kernel modules.
index c59d26068a6401990343e26c03002fcc4022ef98..97f8911ea339e69cc23228ef7d63b4381e883b34 100644 (file)
@@ -61,9 +61,12 @@ static inline void * __init xbc_alloc_mem(size_t size)
        return memblock_alloc(size, SMP_CACHE_BYTES);
 }
 
-static inline void __init xbc_free_mem(void *addr, size_t size)
+static inline void __init xbc_free_mem(void *addr, size_t size, bool early)
 {
-       memblock_free(addr, size);
+       if (early)
+               memblock_free(addr, size);
+       else if (addr)
+               memblock_free_late(__pa(addr), size);
 }
 
 #else /* !__KERNEL__ */
@@ -73,7 +76,7 @@ static inline void *xbc_alloc_mem(size_t size)
        return malloc(size);
 }
 
-static inline void xbc_free_mem(void *addr, size_t size)
+static inline void xbc_free_mem(void *addr, size_t size, bool early)
 {
        free(addr);
 }
@@ -898,19 +901,20 @@ static int __init xbc_parse_tree(void)
 }
 
 /**
- * xbc_exit() - Clean up all parsed bootconfig
+ * _xbc_exit() - Clean up all parsed bootconfig
+ * @early: Set true if this is called before budy system is initialized.
  *
  * This clears all data structures of parsed bootconfig on memory.
  * If you need to reuse xbc_init() with new boot config, you can
  * use this.
  */
-void __init xbc_exit(void)
+void __init _xbc_exit(bool early)
 {
-       xbc_free_mem(xbc_data, xbc_data_size);
+       xbc_free_mem(xbc_data, xbc_data_size, early);
        xbc_data = NULL;
        xbc_data_size = 0;
        xbc_node_num = 0;
-       xbc_free_mem(xbc_nodes, sizeof(struct xbc_node) * XBC_NODE_MAX);
+       xbc_free_mem(xbc_nodes, sizeof(struct xbc_node) * XBC_NODE_MAX, early);
        xbc_nodes = NULL;
        brace_index = 0;
 }
@@ -963,7 +967,7 @@ int __init xbc_init(const char *data, size_t size, const char **emsg, int *epos)
        if (!xbc_nodes) {
                if (emsg)
                        *emsg = "Failed to allocate bootconfig nodes";
-               xbc_exit();
+               _xbc_exit(true);
                return -ENOMEM;
        }
        memset(xbc_nodes, 0, sizeof(struct xbc_node) * XBC_NODE_MAX);
@@ -977,7 +981,7 @@ int __init xbc_init(const char *data, size_t size, const char **emsg, int *epos)
                        *epos = xbc_err_pos;
                if (emsg)
                        *emsg = xbc_err_msg;
-               xbc_exit();
+               _xbc_exit(true);
        } else
                ret = xbc_node_num;
 
index c78f335fa98137664745e6593c98b707a528bf34..f2c5e7910bb19122f29d93b0c1e896638738b1a3 100644 (file)
@@ -302,7 +302,11 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords)
                } else {
                        for (end = buf; *end && !isspace(*end); end++)
                                ;
-                       BUG_ON(end == buf);
+                       if (end == buf) {
+                               pr_err("parse err after word:%d=%s\n", nwords,
+                                      nwords ? words[nwords - 1] : "<none>");
+                               return -EINVAL;
+                       }
                }
 
                /* `buf' is start of word, `end' is one past its end */
index 68b45c82c37a6981bb72cc79ab4c4fcac8e2e489..7bc2220fea805855fadd0a1ed347ea2b9195e9e9 100644 (file)
@@ -1124,7 +1124,7 @@ static ssize_t extract_user_to_sg(struct iov_iter *iter,
        do {
                res = iov_iter_extract_pages(iter, &pages, maxsize, sg_max,
                                             extraction_flags, &off);
-               if (res < 0)
+               if (res <= 0)
                        goto failed;
 
                len = res;
index 68c97387aa54e2728b79b2cacf23815fcb2f90ca..cd8f23455285100036cc4f6971c81017cc0849ad 100644 (file)
@@ -627,10 +627,10 @@ depot_stack_handle_t stack_depot_save_flags(unsigned long *entries,
                /*
                 * Zero out zone modifiers, as we don't have specific zone
                 * requirements. Keep the flags related to allocation in atomic
-                * contexts and I/O.
+                * contexts, I/O, nolockdep.
                 */
                alloc_flags &= ~GFP_ZONEMASK;
-               alloc_flags &= (GFP_ATOMIC | GFP_KERNEL);
+               alloc_flags &= (GFP_ATOMIC | GFP_KERNEL | __GFP_NOLOCKDEP);
                alloc_flags |= __GFP_NOWARN;
                page = alloc_pages(alloc_flags, DEPOT_POOL_ORDER);
                if (page)
index 5fc107f61934c28bd38b6997cd070ee8a25185b5..a1c983d148f16fe34493d6b933577556832bcdf6 100644 (file)
@@ -44,9 +44,10 @@ const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type)
        case ubsan_shift_out_of_bounds:
                return "UBSAN: shift out of bounds";
 #endif
-#ifdef CONFIG_UBSAN_DIV_ZERO
+#if defined(CONFIG_UBSAN_DIV_ZERO) || defined(CONFIG_UBSAN_SIGNED_WRAP)
        /*
-        * SanitizerKind::IntegerDivideByZero emits
+        * SanitizerKind::IntegerDivideByZero and
+        * SanitizerKind::SignedIntegerOverflow emit
         * SanitizerHandler::DivremOverflow.
         */
        case ubsan_divrem_overflow:
@@ -77,6 +78,19 @@ const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type)
                return "UBSAN: alignment assumption";
        case ubsan_type_mismatch:
                return "UBSAN: type mismatch";
+#endif
+#ifdef CONFIG_UBSAN_SIGNED_WRAP
+       /*
+        * SanitizerKind::SignedIntegerOverflow emits
+        * SanitizerHandler::AddOverflow, SanitizerHandler::SubOverflow,
+        * or SanitizerHandler::MulOverflow.
+        */
+       case ubsan_add_overflow:
+               return "UBSAN: integer addition overflow";
+       case ubsan_sub_overflow:
+               return "UBSAN: integer subtraction overflow";
+       case ubsan_mul_overflow:
+               return "UBSAN: integer multiplication overflow";
 #endif
        default:
                return "UBSAN: unrecognized failure code";
index af8edadc05d1b87200050bd34ff3d58ec52abd52..1611e73b1121b1b9031356ccac6b765c60327ba1 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1206,6 +1206,22 @@ static long __get_user_pages(struct mm_struct *mm,
 
                /* first iteration or cross vma bound */
                if (!vma || start >= vma->vm_end) {
+                       /*
+                        * MADV_POPULATE_(READ|WRITE) wants to handle VMA
+                        * lookups+error reporting differently.
+                        */
+                       if (gup_flags & FOLL_MADV_POPULATE) {
+                               vma = vma_lookup(mm, start);
+                               if (!vma) {
+                                       ret = -ENOMEM;
+                                       goto out;
+                               }
+                               if (check_vma_flags(vma, gup_flags)) {
+                                       ret = -EINVAL;
+                                       goto out;
+                               }
+                               goto retry;
+                       }
                        vma = gup_vma_lookup(mm, start);
                        if (!vma && in_gate_area(mm, start)) {
                                ret = get_gate_page(mm, start & PAGE_MASK,
@@ -1685,35 +1701,35 @@ long populate_vma_page_range(struct vm_area_struct *vma,
 }
 
 /*
- * faultin_vma_page_range() - populate (prefault) page tables inside the
- *                           given VMA range readable/writable
+ * faultin_page_range() - populate (prefault) page tables inside the
+ *                       given range readable/writable
  *
  * This takes care of mlocking the pages, too, if VM_LOCKED is set.
  *
- * @vma: target vma
+ * @mm: the mm to populate page tables in
  * @start: start address
  * @end: end address
  * @write: whether to prefault readable or writable
  * @locked: whether the mmap_lock is still held
  *
- * Returns either number of processed pages in the vma, or a negative error
- * code on error (see __get_user_pages()).
+ * Returns either number of processed pages in the MM, or a negative error
+ * code on error (see __get_user_pages()). Note that this function reports
+ * errors related to VMAs, such as incompatible mappings, as expected by
+ * MADV_POPULATE_(READ|WRITE).
  *
- * vma->vm_mm->mmap_lock must be held. The range must be page-aligned and
- * covered by the VMA. If it's released, *@locked will be set to 0.
+ * The range must be page-aligned.
+ *
+ * mm->mmap_lock must be held. If it's released, *@locked will be set to 0.
  */
-long faultin_vma_page_range(struct vm_area_struct *vma, unsigned long start,
-                           unsigned long end, bool write, int *locked)
+long faultin_page_range(struct mm_struct *mm, unsigned long start,
+                       unsigned long end, bool write, int *locked)
 {
-       struct mm_struct *mm = vma->vm_mm;
        unsigned long nr_pages = (end - start) / PAGE_SIZE;
        int gup_flags;
        long ret;
 
        VM_BUG_ON(!PAGE_ALIGNED(start));
        VM_BUG_ON(!PAGE_ALIGNED(end));
-       VM_BUG_ON_VMA(start < vma->vm_start, vma);
-       VM_BUG_ON_VMA(end > vma->vm_end, vma);
        mmap_assert_locked(mm);
 
        /*
@@ -1725,19 +1741,13 @@ long faultin_vma_page_range(struct vm_area_struct *vma, unsigned long start,
         *                a poisoned page.
         * !FOLL_FORCE: Require proper access permissions.
         */
-       gup_flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_UNLOCKABLE;
+       gup_flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_UNLOCKABLE |
+                   FOLL_MADV_POPULATE;
        if (write)
                gup_flags |= FOLL_WRITE;
 
-       /*
-        * We want to report -EINVAL instead of -EFAULT for any permission
-        * problems or incompatible mappings.
-        */
-       if (check_vma_flags(vma, gup_flags))
-               return -EINVAL;
-
-       ret = __get_user_pages(mm, start, nr_pages, gup_flags,
-                              NULL, locked);
+       ret = __get_user_pages_locked(mm, start, nr_pages, NULL, locked,
+                                     gup_flags);
        lru_add_drain();
        return ret;
 }
index 9859aa4f755380a88013c70791e6e6df90ce861f..89f58c7603b255feb3dceaccfee603a503c40e49 100644 (file)
@@ -2259,9 +2259,6 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm
                        goto unlock_ptls;
                }
 
-               folio_move_anon_rmap(src_folio, dst_vma);
-               WRITE_ONCE(src_folio->index, linear_page_index(dst_vma, dst_addr));
-
                src_pmdval = pmdp_huge_clear_flush(src_vma, src_addr, src_pmd);
                /* Folio got pinned from under us. Put it back and fail the move. */
                if (folio_maybe_dma_pinned(src_folio)) {
@@ -2270,6 +2267,9 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm
                        goto unlock_ptls;
                }
 
+               folio_move_anon_rmap(src_folio, dst_vma);
+               WRITE_ONCE(src_folio->index, linear_page_index(dst_vma, dst_addr));
+
                _dst_pmd = mk_huge_pmd(&src_folio->page, dst_vma->vm_page_prot);
                /* Follow mremap() behavior and treat the entry dirty after the move */
                _dst_pmd = pmd_mkwrite(pmd_mkdirty(_dst_pmd), dst_vma);
index 23ef240ba48a60a77102f7bf1beb2e76a987486d..ce7be5c244429f71bc686399889fba7f4b6e1cf8 100644 (file)
@@ -1624,7 +1624,7 @@ static inline void __clear_hugetlb_destructor(struct hstate *h,
 {
        lockdep_assert_held(&hugetlb_lock);
 
-       folio_clear_hugetlb(folio);
+       __folio_clear_hugetlb(folio);
 }
 
 /*
@@ -1711,7 +1711,7 @@ static void add_hugetlb_folio(struct hstate *h, struct folio *folio,
                h->surplus_huge_pages_node[nid]++;
        }
 
-       folio_set_hugetlb(folio);
+       __folio_set_hugetlb(folio);
        folio_change_private(folio, NULL);
        /*
         * We have to set hugetlb_vmemmap_optimized again as above
@@ -1781,7 +1781,7 @@ static void __update_and_free_hugetlb_folio(struct hstate *h,
         * If vmemmap pages were allocated above, then we need to clear the
         * hugetlb destructor under the hugetlb lock.
         */
-       if (clear_dtor) {
+       if (folio_test_hugetlb(folio)) {
                spin_lock_irq(&hugetlb_lock);
                __clear_hugetlb_destructor(h, folio);
                spin_unlock_irq(&hugetlb_lock);
@@ -2049,7 +2049,7 @@ static void __prep_account_new_huge_page(struct hstate *h, int nid)
 
 static void init_new_hugetlb_folio(struct hstate *h, struct folio *folio)
 {
-       folio_set_hugetlb(folio);
+       __folio_set_hugetlb(folio);
        INIT_LIST_HEAD(&folio->lru);
        hugetlb_set_folio_subpool(folio, NULL);
        set_hugetlb_cgroup(folio, NULL);
@@ -2159,22 +2159,6 @@ static bool prep_compound_gigantic_folio_for_demote(struct folio *folio,
        return __prep_compound_gigantic_folio(folio, order, true);
 }
 
-/*
- * PageHuge() only returns true for hugetlbfs pages, but not for normal or
- * transparent huge pages.  See the PageTransHuge() documentation for more
- * details.
- */
-int PageHuge(const struct page *page)
-{
-       const struct folio *folio;
-
-       if (!PageCompound(page))
-               return 0;
-       folio = page_folio(page);
-       return folio_test_hugetlb(folio);
-}
-EXPORT_SYMBOL_GPL(PageHuge);
-
 /*
  * Find and lock address space (mapping) in write mode.
  *
@@ -3268,9 +3252,12 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
 
                rsv_adjust = hugepage_subpool_put_pages(spool, 1);
                hugetlb_acct_memory(h, -rsv_adjust);
-               if (deferred_reserve)
+               if (deferred_reserve) {
+                       spin_lock_irq(&hugetlb_lock);
                        hugetlb_cgroup_uncharge_folio_rsvd(hstate_index(h),
                                        pages_per_huge_page(h), folio);
+                       spin_unlock_irq(&hugetlb_lock);
+               }
        }
 
        if (!memcg_charge_ret)
@@ -6274,6 +6261,12 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
                                                        VM_UFFD_MISSING);
                }
 
+               if (!(vma->vm_flags & VM_MAYSHARE)) {
+                       ret = vmf_anon_prepare(vmf);
+                       if (unlikely(ret))
+                               goto out;
+               }
+
                folio = alloc_hugetlb_folio(vma, haddr, 0);
                if (IS_ERR(folio)) {
                        /*
@@ -6310,15 +6303,12 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
                                 */
                                restore_reserve_on_error(h, vma, haddr, folio);
                                folio_put(folio);
+                               ret = VM_FAULT_SIGBUS;
                                goto out;
                        }
                        new_pagecache_folio = true;
                } else {
                        folio_lock(folio);
-
-                       ret = vmf_anon_prepare(vmf);
-                       if (unlikely(ret))
-                               goto backout_unlocked;
                        anon_rmap = 1;
                }
        } else {
@@ -7044,9 +7034,13 @@ long hugetlb_change_protection(struct vm_area_struct *vma,
                        if (!pte_same(pte, newpte))
                                set_huge_pte_at(mm, address, ptep, newpte, psize);
                } else if (unlikely(is_pte_marker(pte))) {
-                       /* No other markers apply for now. */
-                       WARN_ON_ONCE(!pte_marker_uffd_wp(pte));
-                       if (uffd_wp_resolve)
+                       /*
+                        * Do nothing on a poison marker; page is
+                        * corrupted, permissons do not apply.  Here
+                        * pte_marker_uffd_wp()==true implies !poison
+                        * because they're mutual exclusive.
+                        */
+                       if (pte_marker_uffd_wp(pte) && uffd_wp_resolve)
                                /* Safe to modify directly (non-present->none). */
                                huge_pte_clear(mm, address, ptep, psize);
                } else if (!huge_pte_none(pte)) {
index 7e486f2c502cee245991e2468a0655228a81aef5..07ad2675a88b4798b140d3af3a303a20519cddc3 100644 (file)
@@ -686,9 +686,8 @@ struct anon_vma *folio_anon_vma(struct folio *folio);
 void unmap_mapping_folio(struct folio *folio);
 extern long populate_vma_page_range(struct vm_area_struct *vma,
                unsigned long start, unsigned long end, int *locked);
-extern long faultin_vma_page_range(struct vm_area_struct *vma,
-                                  unsigned long start, unsigned long end,
-                                  bool write, int *locked);
+extern long faultin_page_range(struct mm_struct *mm, unsigned long start,
+               unsigned long end, bool write, int *locked);
 extern bool mlock_future_ok(struct mm_struct *mm, unsigned long flags,
                               unsigned long bytes);
 
@@ -1127,10 +1126,13 @@ enum {
        FOLL_FAST_ONLY = 1 << 20,
        /* allow unlocking the mmap lock */
        FOLL_UNLOCKABLE = 1 << 21,
+       /* VMA lookup+checks compatible with MADV_POPULATE_(READ|WRITE) */
+       FOLL_MADV_POPULATE = 1 << 22,
 };
 
 #define INTERNAL_GUP_FLAGS (FOLL_TOUCH | FOLL_TRIED | FOLL_REMOTE | FOLL_PIN | \
-                           FOLL_FAST_ONLY | FOLL_UNLOCKABLE)
+                           FOLL_FAST_ONLY | FOLL_UNLOCKABLE | \
+                           FOLL_MADV_POPULATE)
 
 /*
  * Indicates for which pages that are write-protected in the page table,
index 44a498c94158c882c624eac2e29a5f07d854e322..1a073fcc4c0c021496667619a20f6ee1afaef7c0 100644 (file)
@@ -908,27 +908,14 @@ static long madvise_populate(struct vm_area_struct *vma,
 {
        const bool write = behavior == MADV_POPULATE_WRITE;
        struct mm_struct *mm = vma->vm_mm;
-       unsigned long tmp_end;
        int locked = 1;
        long pages;
 
        *prev = vma;
 
        while (start < end) {
-               /*
-                * We might have temporarily dropped the lock. For example,
-                * our VMA might have been split.
-                */
-               if (!vma || start >= vma->vm_end) {
-                       vma = vma_lookup(mm, start);
-                       if (!vma)
-                               return -ENOMEM;
-               }
-
-               tmp_end = min_t(unsigned long, end, vma->vm_end);
                /* Populate (prefault) page tables readable/writable. */
-               pages = faultin_vma_page_range(vma, start, tmp_end, write,
-                                              &locked);
+               pages = faultin_page_range(mm, start, end, write, &locked);
                if (!locked) {
                        mmap_read_lock(mm);
                        locked = 1;
@@ -949,7 +936,7 @@ static long madvise_populate(struct vm_area_struct *vma,
                                pr_warn_once("%s: unhandled return value: %ld\n",
                                             __func__, pages);
                                fallthrough;
-                       case -ENOMEM:
+                       case -ENOMEM: /* No VMA or out of memory. */
                                return -ENOMEM;
                        }
                }
index 9349948f1abfd120977706bbda23456999f057bc..9e62a00b46ddee5899f85cfc252dabd7c0d04121 100644 (file)
@@ -154,11 +154,23 @@ static int __page_handle_poison(struct page *page)
 {
        int ret;
 
-       zone_pcp_disable(page_zone(page));
+       /*
+        * zone_pcp_disable() can't be used here. It will
+        * hold pcp_batch_high_lock and dissolve_free_huge_page() might hold
+        * cpu_hotplug_lock via static_key_slow_dec() when hugetlb vmemmap
+        * optimization is enabled. This will break current lock dependency
+        * chain and leads to deadlock.
+        * Disabling pcp before dissolving the page was a deterministic
+        * approach because we made sure that those pages cannot end up in any
+        * PCP list. Draining PCP lists expels those pages to the buddy system,
+        * but nothing guarantees that those pages do not get back to a PCP
+        * queue if we need to refill those.
+        */
        ret = dissolve_free_huge_page(page);
-       if (!ret)
+       if (!ret) {
+               drain_all_pages(page_zone(page));
                ret = take_page_off_buddy(page);
-       zone_pcp_enable(page_zone(page));
+       }
 
        return ret;
 }
index d17d1351ec84af6ae4f49dc34d4c27c56bf77468..742f432e5bf06f560abdc675d658401f76df5237 100644 (file)
@@ -118,7 +118,6 @@ static __init void init_page_owner(void)
        register_dummy_stack();
        register_failure_stack();
        register_early_stack();
-       static_branch_enable(&page_owner_inited);
        init_early_allocated_pages();
        /* Initialize dummy and failure stacks and link them to stack_list */
        dummy_stack.stack_record = __stack_depot_get_stack_record(dummy_handle);
@@ -129,6 +128,7 @@ static __init void init_page_owner(void)
                refcount_set(&failure_stack.stack_record->count, 1);
        dummy_stack.next = &failure_stack;
        stack_list = &dummy_stack;
+       static_branch_enable(&page_owner_inited);
 }
 
 struct page_ext_operations page_owner_ops = {
@@ -196,7 +196,8 @@ static void add_stack_record_to_list(struct stack_record *stack_record,
        spin_unlock_irqrestore(&stack_list_lock, flags);
 }
 
-static void inc_stack_record_count(depot_stack_handle_t handle, gfp_t gfp_mask)
+static void inc_stack_record_count(depot_stack_handle_t handle, gfp_t gfp_mask,
+                                  int nr_base_pages)
 {
        struct stack_record *stack_record = __stack_depot_get_stack_record(handle);
 
@@ -217,20 +218,74 @@ static void inc_stack_record_count(depot_stack_handle_t handle, gfp_t gfp_mask)
                        /* Add the new stack_record to our list */
                        add_stack_record_to_list(stack_record, gfp_mask);
        }
-       refcount_inc(&stack_record->count);
+       refcount_add(nr_base_pages, &stack_record->count);
 }
 
-static void dec_stack_record_count(depot_stack_handle_t handle)
+static void dec_stack_record_count(depot_stack_handle_t handle,
+                                  int nr_base_pages)
 {
        struct stack_record *stack_record = __stack_depot_get_stack_record(handle);
 
-       if (stack_record)
-               refcount_dec(&stack_record->count);
+       if (!stack_record)
+               return;
+
+       if (refcount_sub_and_test(nr_base_pages, &stack_record->count))
+               pr_warn("%s: refcount went to 0 for %u handle\n", __func__,
+                       handle);
 }
 
-void __reset_page_owner(struct page *page, unsigned short order)
+static inline void __update_page_owner_handle(struct page_ext *page_ext,
+                                             depot_stack_handle_t handle,
+                                             unsigned short order,
+                                             gfp_t gfp_mask,
+                                             short last_migrate_reason, u64 ts_nsec,
+                                             pid_t pid, pid_t tgid, char *comm)
 {
        int i;
+       struct page_owner *page_owner;
+
+       for (i = 0; i < (1 << order); i++) {
+               page_owner = get_page_owner(page_ext);
+               page_owner->handle = handle;
+               page_owner->order = order;
+               page_owner->gfp_mask = gfp_mask;
+               page_owner->last_migrate_reason = last_migrate_reason;
+               page_owner->pid = pid;
+               page_owner->tgid = tgid;
+               page_owner->ts_nsec = ts_nsec;
+               strscpy(page_owner->comm, comm,
+                       sizeof(page_owner->comm));
+               __set_bit(PAGE_EXT_OWNER, &page_ext->flags);
+               __set_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
+               page_ext = page_ext_next(page_ext);
+       }
+}
+
+static inline void __update_page_owner_free_handle(struct page_ext *page_ext,
+                                                  depot_stack_handle_t handle,
+                                                  unsigned short order,
+                                                  pid_t pid, pid_t tgid,
+                                                  u64 free_ts_nsec)
+{
+       int i;
+       struct page_owner *page_owner;
+
+       for (i = 0; i < (1 << order); i++) {
+               page_owner = get_page_owner(page_ext);
+               /* Only __reset_page_owner() wants to clear the bit */
+               if (handle) {
+                       __clear_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
+                       page_owner->free_handle = handle;
+               }
+               page_owner->free_ts_nsec = free_ts_nsec;
+               page_owner->free_pid = current->pid;
+               page_owner->free_tgid = current->tgid;
+               page_ext = page_ext_next(page_ext);
+       }
+}
+
+void __reset_page_owner(struct page *page, unsigned short order)
+{
        struct page_ext *page_ext;
        depot_stack_handle_t handle;
        depot_stack_handle_t alloc_handle;
@@ -245,16 +300,10 @@ void __reset_page_owner(struct page *page, unsigned short order)
        alloc_handle = page_owner->handle;
 
        handle = save_stack(GFP_NOWAIT | __GFP_NOWARN);
-       for (i = 0; i < (1 << order); i++) {
-               __clear_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
-               page_owner->free_handle = handle;
-               page_owner->free_ts_nsec = free_ts_nsec;
-               page_owner->free_pid = current->pid;
-               page_owner->free_tgid = current->tgid;
-               page_ext = page_ext_next(page_ext);
-               page_owner = get_page_owner(page_ext);
-       }
+       __update_page_owner_free_handle(page_ext, handle, order, current->pid,
+                                       current->tgid, free_ts_nsec);
        page_ext_put(page_ext);
+
        if (alloc_handle != early_handle)
                /*
                 * early_handle is being set as a handle for all those
@@ -263,39 +312,14 @@ void __reset_page_owner(struct page *page, unsigned short order)
                 * the machinery is not ready yet, we cannot decrement
                 * their refcount either.
                 */
-               dec_stack_record_count(alloc_handle);
-}
-
-static inline void __set_page_owner_handle(struct page_ext *page_ext,
-                                       depot_stack_handle_t handle,
-                                       unsigned short order, gfp_t gfp_mask)
-{
-       struct page_owner *page_owner;
-       int i;
-       u64 ts_nsec = local_clock();
-
-       for (i = 0; i < (1 << order); i++) {
-               page_owner = get_page_owner(page_ext);
-               page_owner->handle = handle;
-               page_owner->order = order;
-               page_owner->gfp_mask = gfp_mask;
-               page_owner->last_migrate_reason = -1;
-               page_owner->pid = current->pid;
-               page_owner->tgid = current->tgid;
-               page_owner->ts_nsec = ts_nsec;
-               strscpy(page_owner->comm, current->comm,
-                       sizeof(page_owner->comm));
-               __set_bit(PAGE_EXT_OWNER, &page_ext->flags);
-               __set_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
-
-               page_ext = page_ext_next(page_ext);
-       }
+               dec_stack_record_count(alloc_handle, 1 << order);
 }
 
 noinline void __set_page_owner(struct page *page, unsigned short order,
                                        gfp_t gfp_mask)
 {
        struct page_ext *page_ext;
+       u64 ts_nsec = local_clock();
        depot_stack_handle_t handle;
 
        handle = save_stack(gfp_mask);
@@ -303,9 +327,11 @@ noinline void __set_page_owner(struct page *page, unsigned short order,
        page_ext = page_ext_get(page);
        if (unlikely(!page_ext))
                return;
-       __set_page_owner_handle(page_ext, handle, order, gfp_mask);
+       __update_page_owner_handle(page_ext, handle, order, gfp_mask, -1,
+                                  current->pid, current->tgid, ts_nsec,
+                                  current->comm);
        page_ext_put(page_ext);
-       inc_stack_record_count(handle, gfp_mask);
+       inc_stack_record_count(handle, gfp_mask, 1 << order);
 }
 
 void __set_page_owner_migrate_reason(struct page *page, int reason)
@@ -340,9 +366,12 @@ void __split_page_owner(struct page *page, int old_order, int new_order)
 
 void __folio_copy_owner(struct folio *newfolio, struct folio *old)
 {
+       int i;
        struct page_ext *old_ext;
        struct page_ext *new_ext;
-       struct page_owner *old_page_owner, *new_page_owner;
+       struct page_owner *old_page_owner;
+       struct page_owner *new_page_owner;
+       depot_stack_handle_t migrate_handle;
 
        old_ext = page_ext_get(&old->page);
        if (unlikely(!old_ext))
@@ -356,30 +385,32 @@ void __folio_copy_owner(struct folio *newfolio, struct folio *old)
 
        old_page_owner = get_page_owner(old_ext);
        new_page_owner = get_page_owner(new_ext);
-       new_page_owner->order = old_page_owner->order;
-       new_page_owner->gfp_mask = old_page_owner->gfp_mask;
-       new_page_owner->last_migrate_reason =
-               old_page_owner->last_migrate_reason;
-       new_page_owner->handle = old_page_owner->handle;
-       new_page_owner->pid = old_page_owner->pid;
-       new_page_owner->tgid = old_page_owner->tgid;
-       new_page_owner->free_pid = old_page_owner->free_pid;
-       new_page_owner->free_tgid = old_page_owner->free_tgid;
-       new_page_owner->ts_nsec = old_page_owner->ts_nsec;
-       new_page_owner->free_ts_nsec = old_page_owner->ts_nsec;
-       strcpy(new_page_owner->comm, old_page_owner->comm);
-
+       migrate_handle = new_page_owner->handle;
+       __update_page_owner_handle(new_ext, old_page_owner->handle,
+                                  old_page_owner->order, old_page_owner->gfp_mask,
+                                  old_page_owner->last_migrate_reason,
+                                  old_page_owner->ts_nsec, old_page_owner->pid,
+                                  old_page_owner->tgid, old_page_owner->comm);
+       /*
+        * Do not proactively clear PAGE_EXT_OWNER{_ALLOCATED} bits as the folio
+        * will be freed after migration. Keep them until then as they may be
+        * useful.
+        */
+       __update_page_owner_free_handle(new_ext, 0, old_page_owner->order,
+                                       old_page_owner->free_pid,
+                                       old_page_owner->free_tgid,
+                                       old_page_owner->free_ts_nsec);
        /*
-        * We don't clear the bit on the old folio as it's going to be freed
-        * after migration. Until then, the info can be useful in case of
-        * a bug, and the overall stats will be off a bit only temporarily.
-        * Also, migrate_misplaced_transhuge_page() can still fail the
-        * migration and then we want the old folio to retain the info. But
-        * in that case we also don't need to explicitly clear the info from
-        * the new page, which will be freed.
+        * We linked the original stack to the new folio, we need to do the same
+        * for the new one and the old folio otherwise there will be an imbalance
+        * when subtracting those pages from the stack.
         */
-       __set_bit(PAGE_EXT_OWNER, &new_ext->flags);
-       __set_bit(PAGE_EXT_OWNER_ALLOCATED, &new_ext->flags);
+       for (i = 0; i < (1 << new_page_owner->order); i++) {
+               old_page_owner->handle = migrate_handle;
+               old_ext = page_ext_next(old_ext);
+               old_page_owner = get_page_owner(old_ext);
+       }
+
        page_ext_put(new_ext);
        page_ext_put(old_ext);
 }
@@ -787,8 +818,9 @@ static void init_pages_in_zone(pg_data_t *pgdat, struct zone *zone)
                                goto ext_put_continue;
 
                        /* Found early allocated page */
-                       __set_page_owner_handle(page_ext, early_handle,
-                                               0, 0);
+                       __update_page_owner_handle(page_ext, early_handle, 0, 0,
+                                                  -1, local_clock(), current->pid,
+                                                  current->tgid, current->comm);
                        count++;
 ext_put_continue:
                        page_ext_put(page_ext);
@@ -840,13 +872,11 @@ static void *stack_start(struct seq_file *m, loff_t *ppos)
                 * value of stack_list.
                 */
                stack = smp_load_acquire(&stack_list);
+               m->private = stack;
        } else {
                stack = m->private;
-               stack = stack->next;
        }
 
-       m->private = stack;
-
        return stack;
 }
 
@@ -861,11 +891,11 @@ static void *stack_next(struct seq_file *m, void *v, loff_t *ppos)
        return stack;
 }
 
-static unsigned long page_owner_stack_threshold;
+static unsigned long page_owner_pages_threshold;
 
 static int stack_print(struct seq_file *m, void *v)
 {
-       int i, stack_count;
+       int i, nr_base_pages;
        struct stack *stack = v;
        unsigned long *entries;
        unsigned long nr_entries;
@@ -876,14 +906,14 @@ static int stack_print(struct seq_file *m, void *v)
 
        nr_entries = stack_record->size;
        entries = stack_record->entries;
-       stack_count = refcount_read(&stack_record->count) - 1;
+       nr_base_pages = refcount_read(&stack_record->count) - 1;
 
-       if (stack_count < 1 || stack_count < page_owner_stack_threshold)
+       if (nr_base_pages < 1 || nr_base_pages < page_owner_pages_threshold)
                return 0;
 
        for (i = 0; i < nr_entries; i++)
                seq_printf(m, " %pS\n", (void *)entries[i]);
-       seq_printf(m, "stack_count: %d\n\n", stack_count);
+       seq_printf(m, "nr_base_pages: %d\n\n", nr_base_pages);
 
        return 0;
 }
@@ -913,13 +943,13 @@ static const struct file_operations page_owner_stack_operations = {
 
 static int page_owner_threshold_get(void *data, u64 *val)
 {
-       *val = READ_ONCE(page_owner_stack_threshold);
+       *val = READ_ONCE(page_owner_pages_threshold);
        return 0;
 }
 
 static int page_owner_threshold_set(void *data, u64 val)
 {
-       WRITE_ONCE(page_owner_stack_threshold, val);
+       WRITE_ONCE(page_owner_pages_threshold, val);
        return 0;
 }
 
index 0aad0d9a621b80e7a3f758125806bfb64e984c12..94ab99b6b574a461e34bb875fdec497ad24728ce 100644 (file)
@@ -748,12 +748,6 @@ static long shmem_unused_huge_count(struct super_block *sb,
 
 #define shmem_huge SHMEM_HUGE_DENY
 
-bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force,
-                  struct mm_struct *mm, unsigned long vm_flags)
-{
-       return false;
-}
-
 static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
                struct shrink_control *sc, unsigned long nr_to_split)
 {
index caed028945b046cf4caa4c842abfc900ef0a45fb..6f8850c44b6166d363d20813732d9b1befc22c61 100644 (file)
@@ -1331,15 +1331,22 @@ static unsigned long zswap_shrinker_count(struct shrinker *shrinker,
        if (!gfp_has_io_fs(sc->gfp_mask))
                return 0;
 
-#ifdef CONFIG_MEMCG_KMEM
-       mem_cgroup_flush_stats(memcg);
-       nr_backing = memcg_page_state(memcg, MEMCG_ZSWAP_B) >> PAGE_SHIFT;
-       nr_stored = memcg_page_state(memcg, MEMCG_ZSWAPPED);
-#else
-       /* use pool stats instead of memcg stats */
-       nr_backing = zswap_pool_total_size >> PAGE_SHIFT;
-       nr_stored = atomic_read(&zswap_nr_stored);
-#endif
+       /*
+        * For memcg, use the cgroup-wide ZSWAP stats since we don't
+        * have them per-node and thus per-lruvec. Careful if memcg is
+        * runtime-disabled: we can get sc->memcg == NULL, which is ok
+        * for the lruvec, but not for memcg_page_state().
+        *
+        * Without memcg, use the zswap pool-wide metrics.
+        */
+       if (!mem_cgroup_disabled()) {
+               mem_cgroup_flush_stats(memcg);
+               nr_backing = memcg_page_state(memcg, MEMCG_ZSWAP_B) >> PAGE_SHIFT;
+               nr_stored = memcg_page_state(memcg, MEMCG_ZSWAPPED);
+       } else {
+               nr_backing = zswap_pool_total_size >> PAGE_SHIFT;
+               nr_stored = atomic_read(&zswap_nr_stored);
+       }
 
        if (!nr_stored)
                return 0;
index f001582345052f8c26e008058ae5f721f8bc224d..9404dd551dfd2850117d4edf9b7fd25e3ba84322 100644 (file)
@@ -478,6 +478,8 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head,
        if (unlikely(!vhdr))
                goto out;
 
+       NAPI_GRO_CB(skb)->network_offsets[NAPI_GRO_CB(skb)->encap_mark] = hlen;
+
        type = vhdr->h_vlan_encapsulated_proto;
 
        ptype = gro_find_receive_by_type(type);
index 558e158c98d01075b7614b754a256124c3700a84..9169efb2f43aa9151131410496d3de24af1f1ccd 100644 (file)
@@ -103,7 +103,7 @@ again:
                        s->ax25_dev = NULL;
                        if (sk->sk_socket) {
                                netdev_put(ax25_dev->dev,
-                                          &ax25_dev->dev_tracker);
+                                          &s->dev_tracker);
                                ax25_dev_put(ax25_dev);
                        }
                        ax25_cb_del(s);
index 3ad74f76983b2426ffda03ac038daea0ea34662a..05346250f7195be3e01b11a0a671193f30316c5e 100644 (file)
@@ -1263,7 +1263,7 @@ u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle)
 
 struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
                                u8 dst_type, bool dst_resolved, u8 sec_level,
-                               u16 conn_timeout, u8 role)
+                               u16 conn_timeout, u8 role, u8 phy, u8 sec_phy)
 {
        struct hci_conn *conn;
        struct smp_irk *irk;
@@ -1326,6 +1326,8 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
        conn->dst_type = dst_type;
        conn->sec_level = BT_SECURITY_LOW;
        conn->conn_timeout = conn_timeout;
+       conn->le_adv_phy = phy;
+       conn->le_adv_sec_phy = sec_phy;
 
        err = hci_connect_le_sync(hdev, conn);
        if (err) {
@@ -2273,7 +2275,7 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
                le = hci_connect_le(hdev, dst, dst_type, false,
                                    BT_SECURITY_LOW,
                                    HCI_LE_CONN_TIMEOUT,
-                                   HCI_ROLE_SLAVE);
+                                   HCI_ROLE_SLAVE, 0, 0);
        else
                le = hci_connect_le_scan(hdev, dst, dst_type,
                                         BT_SECURITY_LOW,
index a8b8cfebe0180cce2fb661e8e5f21a79bf7a7656..4a27e4a17a67449ffd8a37cb057357e20881667c 100644 (file)
@@ -3218,7 +3218,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
                        if (key) {
                                set_bit(HCI_CONN_ENCRYPT, &conn->flags);
 
-                               if (!(hdev->commands[20] & 0x10)) {
+                               if (!read_key_size_capable(hdev)) {
                                        conn->enc_key_size = HCI_LINK_KEY_SIZE;
                                } else {
                                        cp.handle = cpu_to_le16(conn->handle);
@@ -3666,8 +3666,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data,
                 * controller really supports it. If it doesn't, assume
                 * the default size (16).
                 */
-               if (!(hdev->commands[20] & 0x10) ||
-                   test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks)) {
+               if (!read_key_size_capable(hdev)) {
                        conn->enc_key_size = HCI_LINK_KEY_SIZE;
                        goto notify;
                }
@@ -6038,7 +6037,7 @@ static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, void *data,
 static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
                                              bdaddr_t *addr,
                                              u8 addr_type, bool addr_resolved,
-                                             u8 adv_type)
+                                             u8 adv_type, u8 phy, u8 sec_phy)
 {
        struct hci_conn *conn;
        struct hci_conn_params *params;
@@ -6093,7 +6092,7 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
 
        conn = hci_connect_le(hdev, addr, addr_type, addr_resolved,
                              BT_SECURITY_LOW, hdev->def_le_autoconnect_timeout,
-                             HCI_ROLE_MASTER);
+                             HCI_ROLE_MASTER, phy, sec_phy);
        if (!IS_ERR(conn)) {
                /* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned
                 * by higher layer that tried to connect, if no then
@@ -6128,8 +6127,9 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
 
 static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
                               u8 bdaddr_type, bdaddr_t *direct_addr,
-                              u8 direct_addr_type, s8 rssi, u8 *data, u8 len,
-                              bool ext_adv, bool ctl_time, u64 instant)
+                              u8 direct_addr_type, u8 phy, u8 sec_phy, s8 rssi,
+                              u8 *data, u8 len, bool ext_adv, bool ctl_time,
+                              u64 instant)
 {
        struct discovery_state *d = &hdev->discovery;
        struct smp_irk *irk;
@@ -6217,7 +6217,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
         * for advertising reports) and is already verified to be RPA above.
         */
        conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, bdaddr_resolved,
-                                    type);
+                                    type, phy, sec_phy);
        if (!ext_adv && conn && type == LE_ADV_IND &&
            len <= max_adv_len(hdev)) {
                /* Store report for later inclusion by
@@ -6363,7 +6363,8 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, void *data,
                if (info->length <= max_adv_len(hdev)) {
                        rssi = info->data[info->length];
                        process_adv_report(hdev, info->type, &info->bdaddr,
-                                          info->bdaddr_type, NULL, 0, rssi,
+                                          info->bdaddr_type, NULL, 0,
+                                          HCI_ADV_PHY_1M, 0, rssi,
                                           info->data, info->length, false,
                                           false, instant);
                } else {
@@ -6448,6 +6449,8 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, void *data,
                if (legacy_evt_type != LE_ADV_INVALID) {
                        process_adv_report(hdev, legacy_evt_type, &info->bdaddr,
                                           info->bdaddr_type, NULL, 0,
+                                          info->primary_phy,
+                                          info->secondary_phy,
                                           info->rssi, info->data, info->length,
                                           !(evt_type & LE_EXT_ADV_LEGACY_PDU),
                                           false, instant);
@@ -6730,8 +6733,8 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, void *data,
 
                process_adv_report(hdev, info->type, &info->bdaddr,
                                   info->bdaddr_type, &info->direct_addr,
-                                  info->direct_addr_type, info->rssi, NULL, 0,
-                                  false, false, instant);
+                                  info->direct_addr_type, HCI_ADV_PHY_1M, 0,
+                                  info->rssi, NULL, 0, false, false, instant);
        }
 
        hci_dev_unlock(hdev);
index c5d8799046ccffbf798e6f47ffaef3dddcb364ca..4c707eb64e6f63d8e2ea85a7ac12a31060dcf7e4 100644 (file)
@@ -6346,7 +6346,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
 
        plen = sizeof(*cp);
 
-       if (scan_1m(hdev)) {
+       if (scan_1m(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_1M ||
+                             conn->le_adv_sec_phy == HCI_ADV_PHY_1M)) {
                cp->phys |= LE_SCAN_PHY_1M;
                set_ext_conn_params(conn, p);
 
@@ -6354,7 +6355,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
                plen += sizeof(*p);
        }
 
-       if (scan_2m(hdev)) {
+       if (scan_2m(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_2M ||
+                             conn->le_adv_sec_phy == HCI_ADV_PHY_2M)) {
                cp->phys |= LE_SCAN_PHY_2M;
                set_ext_conn_params(conn, p);
 
@@ -6362,7 +6364,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
                plen += sizeof(*p);
        }
 
-       if (scan_coded(hdev)) {
+       if (scan_coded(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_CODED ||
+                                conn->le_adv_sec_phy == HCI_ADV_PHY_CODED)) {
                cp->phys |= LE_SCAN_PHY_CODED;
                set_ext_conn_params(conn, p);
 
index dc089740879363dd0d6d973dcdb4fc05cfc7070a..84fc70862d78aeef25d6ca9e6df7fb468338852e 100644 (file)
@@ -7018,7 +7018,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
                if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
                        hcon = hci_connect_le(hdev, dst, dst_type, false,
                                              chan->sec_level, timeout,
-                                             HCI_ROLE_SLAVE);
+                                             HCI_ROLE_SLAVE, 0, 0);
                else
                        hcon = hci_connect_le_scan(hdev, dst, dst_type,
                                                   chan->sec_level, timeout,
index e7d810b23082f5ffd8ea4b506366b2684f2e1ece..5cc83f906c123ffa7349d26a41c310005920aca5 100644 (file)
@@ -439,7 +439,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
        struct l2cap_chan *chan = l2cap_pi(sk)->chan;
        struct l2cap_options opts;
        struct l2cap_conninfo cinfo;
-       int len, err = 0;
+       int err = 0;
+       size_t len;
        u32 opt;
 
        BT_DBG("sk %p", sk);
@@ -486,7 +487,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
 
                BT_DBG("mode 0x%2.2x", chan->mode);
 
-               len = min_t(unsigned int, len, sizeof(opts));
+               len = min(len, sizeof(opts));
                if (copy_to_user(optval, (char *) &opts, len))
                        err = -EFAULT;
 
@@ -536,7 +537,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
                cinfo.hci_handle = chan->conn->hcon->handle;
                memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);
 
-               len = min_t(unsigned int, len, sizeof(cinfo));
+               len = min(len, sizeof(cinfo));
                if (copy_to_user(optval, (char *) &cinfo, len))
                        err = -EFAULT;
 
index 32ed6e9245a307483e69ccb1cb1dd8c30c023130..965f621ef865adb607a6ccf71f6b2e7429a10a99 100644 (file)
@@ -2623,7 +2623,11 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
                goto failed;
        }
 
-       err = hci_cmd_sync_queue(hdev, add_uuid_sync, cmd, mgmt_class_complete);
+       /* MGMT_OP_ADD_UUID don't require adapter the UP/Running so use
+        * hci_cmd_sync_submit instead of hci_cmd_sync_queue.
+        */
+       err = hci_cmd_sync_submit(hdev, add_uuid_sync, cmd,
+                                 mgmt_class_complete);
        if (err < 0) {
                mgmt_pending_free(cmd);
                goto failed;
@@ -2717,8 +2721,11 @@ update_class:
                goto unlock;
        }
 
-       err = hci_cmd_sync_queue(hdev, remove_uuid_sync, cmd,
-                                mgmt_class_complete);
+       /* MGMT_OP_REMOVE_UUID don't require adapter the UP/Running so use
+        * hci_cmd_sync_submit instead of hci_cmd_sync_queue.
+        */
+       err = hci_cmd_sync_submit(hdev, remove_uuid_sync, cmd,
+                                 mgmt_class_complete);
        if (err < 0)
                mgmt_pending_free(cmd);
 
@@ -2784,8 +2791,11 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
                goto unlock;
        }
 
-       err = hci_cmd_sync_queue(hdev, set_class_sync, cmd,
-                                mgmt_class_complete);
+       /* MGMT_OP_SET_DEV_CLASS don't require adapter the UP/Running so use
+        * hci_cmd_sync_submit instead of hci_cmd_sync_queue.
+        */
+       err = hci_cmd_sync_submit(hdev, set_class_sync, cmd,
+                                 mgmt_class_complete);
        if (err < 0)
                mgmt_pending_free(cmd);
 
@@ -5475,8 +5485,8 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
                goto unlock;
        }
 
-       err = hci_cmd_sync_queue(hdev, mgmt_remove_adv_monitor_sync, cmd,
-                                mgmt_remove_adv_monitor_complete);
+       err = hci_cmd_sync_submit(hdev, mgmt_remove_adv_monitor_sync, cmd,
+                                 mgmt_remove_adv_monitor_complete);
 
        if (err) {
                mgmt_pending_remove(cmd);
index 368e026f4d15ca4711737af941ad30c7b48b827f..5d03c5440b06f843e654ddb0e3d3f83d4dd0cfd9 100644 (file)
@@ -964,7 +964,8 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
        struct sock *sk = sock->sk;
        struct sco_options opts;
        struct sco_conninfo cinfo;
-       int len, err = 0;
+       int err = 0;
+       size_t len;
 
        BT_DBG("sk %p", sk);
 
@@ -986,7 +987,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
 
                BT_DBG("mtu %u", opts.mtu);
 
-               len = min_t(unsigned int, len, sizeof(opts));
+               len = min(len, sizeof(opts));
                if (copy_to_user(optval, (char *)&opts, len))
                        err = -EFAULT;
 
@@ -1004,7 +1005,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
                cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
                memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
 
-               len = min_t(unsigned int, len, sizeof(cinfo));
+               len = min(len, sizeof(cinfo));
                if (copy_to_user(optval, (char *)&cinfo, len))
                        err = -EFAULT;
 
index 7431f89e897b9549a0c35d9431e36b6de2e80022..d7c35f55bd69fb5e7d3add82a4ce7c48c83b8332 100644 (file)
@@ -266,7 +266,7 @@ static void maybe_deliver_addr(struct net_bridge_port *p, struct sk_buff *skb,
        if (skb->dev == p->dev && ether_addr_equal(src, addr))
                return;
 
-       skb = skb_copy(skb, GFP_ATOMIC);
+       skb = pskb_copy(skb, GFP_ATOMIC);
        if (!skb) {
                DEV_STATS_INC(dev, tx_dropped);
                return;
index f21097e734827891f87adb9d0a1f7cebf9f15380..ceaa5a89b947fc574ee2a05003db3de7cc9797b1 100644 (file)
@@ -30,7 +30,7 @@ br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb)
        return netif_receive_skb(skb);
 }
 
-static int br_pass_frame_up(struct sk_buff *skb)
+static int br_pass_frame_up(struct sk_buff *skb, bool promisc)
 {
        struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
        struct net_bridge *br = netdev_priv(brdev);
@@ -65,6 +65,8 @@ static int br_pass_frame_up(struct sk_buff *skb)
        br_multicast_count(br, NULL, skb, br_multicast_igmp_type(skb),
                           BR_MCAST_DIR_TX);
 
+       BR_INPUT_SKB_CB(skb)->promisc = promisc;
+
        return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN,
                       dev_net(indev), NULL, skb, indev, NULL,
                       br_netif_receive_skb);
@@ -82,6 +84,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
        struct net_bridge_mcast *brmctx;
        struct net_bridge_vlan *vlan;
        struct net_bridge *br;
+       bool promisc;
        u16 vid = 0;
        u8 state;
 
@@ -137,7 +140,9 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
        if (p->flags & BR_LEARNING)
                br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, 0);
 
-       local_rcv = !!(br->dev->flags & IFF_PROMISC);
+       promisc = !!(br->dev->flags & IFF_PROMISC);
+       local_rcv = promisc;
+
        if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) {
                /* by definition the broadcast is also a multicast address */
                if (is_broadcast_ether_addr(eth_hdr(skb)->h_dest)) {
@@ -200,7 +205,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
                unsigned long now = jiffies;
 
                if (test_bit(BR_FDB_LOCAL, &dst->flags))
-                       return br_pass_frame_up(skb);
+                       return br_pass_frame_up(skb, false);
 
                if (now != dst->used)
                        dst->used = now;
@@ -213,7 +218,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
        }
 
        if (local_rcv)
-               return br_pass_frame_up(skb);
+               return br_pass_frame_up(skb, promisc);
 
 out:
        return 0;
@@ -386,6 +391,8 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
                                goto forward;
                }
 
+               BR_INPUT_SKB_CB(skb)->promisc = false;
+
                /* The else clause should be hit when nf_hook():
                 *   - returns < 0 (drop/error)
                 *   - returns = 0 (stolen/nf_queue)
index 35e10c5a766d550e0c5cb85cf5a0c4835b52a89d..22e35623c148ac41056d7c24e3996227726ec1a6 100644 (file)
@@ -600,11 +600,17 @@ static unsigned int br_nf_local_in(void *priv,
                                   struct sk_buff *skb,
                                   const struct nf_hook_state *state)
 {
+       bool promisc = BR_INPUT_SKB_CB(skb)->promisc;
        struct nf_conntrack *nfct = skb_nfct(skb);
        const struct nf_ct_hook *ct_hook;
        struct nf_conn *ct;
        int ret;
 
+       if (promisc) {
+               nf_reset_ct(skb);
+               return NF_ACCEPT;
+       }
+
        if (!nfct || skb->pkt_type == PACKET_HOST)
                return NF_ACCEPT;
 
index 2cf4fc756263992eefe6a3580410766fea0c2c1f..f17dbac7d82843091f9131acc68a5a9132fa2eda 100644 (file)
@@ -667,7 +667,7 @@ void br_ifinfo_notify(int event, const struct net_bridge *br,
 {
        u32 filter = RTEXT_FILTER_BRVLAN_COMPRESSED;
 
-       return br_info_notify(event, br, port, filter);
+       br_info_notify(event, br, port, filter);
 }
 
 /*
index 86ea5e6689b5ce49a4b71b383893d2ef5b53d110..d4bedc87b1d8f1bcf96c714fc80078227470550a 100644 (file)
@@ -589,6 +589,7 @@ struct br_input_skb_cb {
 #endif
        u8 proxyarp_replied:1;
        u8 src_port_isolated:1;
+       u8 promisc:1;
 #ifdef CONFIG_BRIDGE_VLAN_FILTERING
        u8 vlan_filtered:1;
 #endif
index 6f877e31709bad3646ea15bf3a96999ed275bdc1..c3c51b9a68265b443326432274e7fd75675e0e28 100644 (file)
@@ -294,18 +294,24 @@ static unsigned int nf_ct_bridge_pre(void *priv, struct sk_buff *skb,
 static unsigned int nf_ct_bridge_in(void *priv, struct sk_buff *skb,
                                    const struct nf_hook_state *state)
 {
-       enum ip_conntrack_info ctinfo;
+       bool promisc = BR_INPUT_SKB_CB(skb)->promisc;
+       struct nf_conntrack *nfct = skb_nfct(skb);
        struct nf_conn *ct;
 
-       if (skb->pkt_type == PACKET_HOST)
+       if (promisc) {
+               nf_reset_ct(skb);
+               return NF_ACCEPT;
+       }
+
+       if (!nfct || skb->pkt_type == PACKET_HOST)
                return NF_ACCEPT;
 
        /* nf_conntrack_confirm() cannot handle concurrent clones,
         * this happens for broad/multicast frames with e.g. macvlan on top
         * of the bridge device.
         */
-       ct = nf_ct_get(skb, &ctinfo);
-       if (!ct || nf_ct_is_confirmed(ct) || nf_ct_is_template(ct))
+       ct = container_of(nfct, struct nf_conn, ct_general);
+       if (nf_ct_is_confirmed(ct) || nf_ct_is_template(ct))
                return NF_ACCEPT;
 
        /* let inet prerouting call conntrack again */
index 984ff8b9d0e1aa5646a7237a8cf0b0a21c2aa559..331848eca7d3109d8043bba1f99e84d8e46d5507 100644 (file)
@@ -3775,6 +3775,10 @@ no_lock_out:
                return rc;
        }
 
+       if (unlikely(READ_ONCE(q->owner) == smp_processor_id())) {
+               kfree_skb_reason(skb, SKB_DROP_REASON_TC_RECLASSIFY_LOOP);
+               return NET_XMIT_DROP;
+       }
        /*
         * Heuristic to force contended enqueues to serialize on a
         * separate lock before trying to get qdisc main lock.
@@ -3814,7 +3818,9 @@ no_lock_out:
                qdisc_run_end(q);
                rc = NET_XMIT_SUCCESS;
        } else {
+               WRITE_ONCE(q->owner, smp_processor_id());
                rc = dev_qdisc_enqueue(skb, q, &to_free, txq);
+               WRITE_ONCE(q->owner, -1);
                if (qdisc_run_begin(q)) {
                        if (unlikely(contended)) {
                                spin_unlock(&q->busylock);
index 8adf95765cdd967a15b2661dfb454db0ccf350b0..ae5254f712c94b0c656fda5fe065ee635252a67e 100644 (file)
@@ -4360,10 +4360,12 @@ static __always_inline int __xdp_do_redirect_frame(struct bpf_redirect_info *ri,
        enum bpf_map_type map_type = ri->map_type;
        void *fwd = ri->tgt_value;
        u32 map_id = ri->map_id;
+       u32 flags = ri->flags;
        struct bpf_map *map;
        int err;
 
        ri->map_id = 0; /* Valid map id idr range: [1,INT_MAX[ */
+       ri->flags = 0;
        ri->map_type = BPF_MAP_TYPE_UNSPEC;
 
        if (unlikely(!xdpf)) {
@@ -4375,11 +4377,20 @@ static __always_inline int __xdp_do_redirect_frame(struct bpf_redirect_info *ri,
        case BPF_MAP_TYPE_DEVMAP:
                fallthrough;
        case BPF_MAP_TYPE_DEVMAP_HASH:
-               map = READ_ONCE(ri->map);
-               if (unlikely(map)) {
+               if (unlikely(flags & BPF_F_BROADCAST)) {
+                       map = READ_ONCE(ri->map);
+
+                       /* The map pointer is cleared when the map is being torn
+                        * down by bpf_clear_redirect_map()
+                        */
+                       if (unlikely(!map)) {
+                               err = -ENOENT;
+                               break;
+                       }
+
                        WRITE_ONCE(ri->map, NULL);
                        err = dev_map_enqueue_multi(xdpf, dev, map,
-                                                   ri->flags & BPF_F_EXCLUDE_INGRESS);
+                                                   flags & BPF_F_EXCLUDE_INGRESS);
                } else {
                        err = dev_map_enqueue(fwd, xdpf, dev);
                }
@@ -4442,9 +4453,9 @@ EXPORT_SYMBOL_GPL(xdp_do_redirect_frame);
 static int xdp_do_generic_redirect_map(struct net_device *dev,
                                       struct sk_buff *skb,
                                       struct xdp_buff *xdp,
-                                      struct bpf_prog *xdp_prog,
-                                      void *fwd,
-                                      enum bpf_map_type map_type, u32 map_id)
+                                      struct bpf_prog *xdp_prog, void *fwd,
+                                      enum bpf_map_type map_type, u32 map_id,
+                                      u32 flags)
 {
        struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
        struct bpf_map *map;
@@ -4454,11 +4465,20 @@ static int xdp_do_generic_redirect_map(struct net_device *dev,
        case BPF_MAP_TYPE_DEVMAP:
                fallthrough;
        case BPF_MAP_TYPE_DEVMAP_HASH:
-               map = READ_ONCE(ri->map);
-               if (unlikely(map)) {
+               if (unlikely(flags & BPF_F_BROADCAST)) {
+                       map = READ_ONCE(ri->map);
+
+                       /* The map pointer is cleared when the map is being torn
+                        * down by bpf_clear_redirect_map()
+                        */
+                       if (unlikely(!map)) {
+                               err = -ENOENT;
+                               break;
+                       }
+
                        WRITE_ONCE(ri->map, NULL);
                        err = dev_map_redirect_multi(dev, skb, xdp_prog, map,
-                                                    ri->flags & BPF_F_EXCLUDE_INGRESS);
+                                                    flags & BPF_F_EXCLUDE_INGRESS);
                } else {
                        err = dev_map_generic_redirect(fwd, skb, xdp_prog);
                }
@@ -4495,9 +4515,11 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
        enum bpf_map_type map_type = ri->map_type;
        void *fwd = ri->tgt_value;
        u32 map_id = ri->map_id;
+       u32 flags = ri->flags;
        int err;
 
        ri->map_id = 0; /* Valid map id idr range: [1,INT_MAX[ */
+       ri->flags = 0;
        ri->map_type = BPF_MAP_TYPE_UNSPEC;
 
        if (map_type == BPF_MAP_TYPE_UNSPEC && map_id == INT_MAX) {
@@ -4517,7 +4539,7 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
                return 0;
        }
 
-       return xdp_do_generic_redirect_map(dev, skb, xdp, xdp_prog, fwd, map_type, map_id);
+       return xdp_do_generic_redirect_map(dev, skb, xdp, xdp_prog, fwd, map_type, map_id, flags);
 err:
        _trace_xdp_redirect_err(dev, xdp_prog, ri->tgt_index, err);
        return err;
index 83f35d99a682c21dae11683fec72074a898fbac2..c7901253a1a8fc1e9425add77014e15b363a1623 100644 (file)
@@ -371,6 +371,7 @@ static inline void skb_gro_reset_offset(struct sk_buff *skb, u32 nhoff)
        const skb_frag_t *frag0;
        unsigned int headlen;
 
+       NAPI_GRO_CB(skb)->network_offset = 0;
        NAPI_GRO_CB(skb)->data_offset = 0;
        headlen = skb_headlen(skb);
        NAPI_GRO_CB(skb)->frag0 = skb->data;
index b99127712e6704dda41636014db46096da171bfd..4096e679f61c76041223b894e3ee4f9a8a051000 100644 (file)
@@ -2123,11 +2123,17 @@ static inline int skb_alloc_rx_flag(const struct sk_buff *skb)
 
 struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask)
 {
-       int headerlen = skb_headroom(skb);
-       unsigned int size = skb_end_offset(skb) + skb->data_len;
-       struct sk_buff *n = __alloc_skb(size, gfp_mask,
-                                       skb_alloc_rx_flag(skb), NUMA_NO_NODE);
+       struct sk_buff *n;
+       unsigned int size;
+       int headerlen;
+
+       if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST))
+               return NULL;
 
+       headerlen = skb_headroom(skb);
+       size = skb_end_offset(skb) + skb->data_len;
+       n = __alloc_skb(size, gfp_mask,
+                       skb_alloc_rx_flag(skb), NUMA_NO_NODE);
        if (!n)
                return NULL;
 
@@ -2455,12 +2461,17 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
        /*
         *      Allocate the copy buffer
         */
-       struct sk_buff *n = __alloc_skb(newheadroom + skb->len + newtailroom,
-                                       gfp_mask, skb_alloc_rx_flag(skb),
-                                       NUMA_NO_NODE);
-       int oldheadroom = skb_headroom(skb);
        int head_copy_len, head_copy_off;
+       struct sk_buff *n;
+       int oldheadroom;
+
+       if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST))
+               return NULL;
 
+       oldheadroom = skb_headroom(skb);
+       n = __alloc_skb(newheadroom + skb->len + newtailroom,
+                       gfp_mask, skb_alloc_rx_flag(skb),
+                       NUMA_NO_NODE);
        if (!n)
                return NULL;
 
index 4d75ef9d24bfa7cbffe642448f5116ac0b943ed2..fd20aae30be23cc2241f081a1d56215f9693cab0 100644 (file)
@@ -1226,11 +1226,8 @@ static void sk_psock_verdict_data_ready(struct sock *sk)
 
                rcu_read_lock();
                psock = sk_psock(sk);
-               if (psock) {
-                       read_lock_bh(&sk->sk_callback_lock);
+               if (psock)
                        sk_psock_data_ready(sk, psock);
-                       read_unlock_bh(&sk->sk_callback_lock);
-               }
                rcu_read_unlock();
        }
 }
index 2edc8b796a4e7326aa44128a0618e15b9aa817de..049c3adeb85044ac78e5adf7dcfb389d21e75652 100644 (file)
@@ -164,17 +164,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
        eth = (struct ethhdr *)skb->data;
        skb_pull_inline(skb, ETH_HLEN);
 
-       if (unlikely(!ether_addr_equal_64bits(eth->h_dest,
-                                             dev->dev_addr))) {
-               if (unlikely(is_multicast_ether_addr_64bits(eth->h_dest))) {
-                       if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast))
-                               skb->pkt_type = PACKET_BROADCAST;
-                       else
-                               skb->pkt_type = PACKET_MULTICAST;
-               } else {
-                       skb->pkt_type = PACKET_OTHERHOST;
-               }
-       }
+       eth_skb_pkt_type(skb, dev);
 
        /*
         * Some variants of DSA tagging don't have an ethertype field
index 55bd72997b31063b7baad350fdcff40e938aecb8..fafb123f798be346c247dac0f9dc8e498e034349 100644 (file)
@@ -1572,6 +1572,7 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb)
        /* The above will be needed by the transport layer if there is one
         * immediately following this IP hdr.
         */
+       NAPI_GRO_CB(skb)->inner_network_offset = off;
 
        /* Note : No need to call skb_gro_postpull_rcsum() here,
         * as we already checked checksum over ipv4 header was 0
index 48741352a88a72e0232977cc9f2cf172f45df89b..c484b1c0fc00a79a45a1c3e7fde230ce59cb67a3 100644 (file)
@@ -1050,6 +1050,11 @@ next:
                        e++;
                }
        }
+
+       /* Don't let NLM_DONE coalesce into a message, even if it could.
+        * Some user space expects NLM_DONE in a separate recv().
+        */
+       err = skb->len;
 out:
 
        cb->args[1] = e;
index e63a3bf99617627e17669f9b3aaee1cbbf178ebf..437e782b9663bb59acb900c0558137ddd401cd02 100644 (file)
@@ -92,6 +92,7 @@
 #include <net/inet_common.h>
 #include <net/ip_fib.h>
 #include <net/l3mdev.h>
+#include <net/addrconf.h>
 
 /*
  *     Build xmit assembly blocks
@@ -1032,6 +1033,8 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr)
        struct icmp_ext_hdr *ext_hdr, _ext_hdr;
        struct icmp_ext_echo_iio *iio, _iio;
        struct net *net = dev_net(skb->dev);
+       struct inet6_dev *in6_dev;
+       struct in_device *in_dev;
        struct net_device *dev;
        char buff[IFNAMSIZ];
        u16 ident_len;
@@ -1115,10 +1118,15 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr)
        /* Fill bits in reply message */
        if (dev->flags & IFF_UP)
                status |= ICMP_EXT_ECHOREPLY_ACTIVE;
-       if (__in_dev_get_rcu(dev) && __in_dev_get_rcu(dev)->ifa_list)
+
+       in_dev = __in_dev_get_rcu(dev);
+       if (in_dev && rcu_access_pointer(in_dev->ifa_list))
                status |= ICMP_EXT_ECHOREPLY_IPV4;
-       if (!list_empty(&rcu_dereference(dev->ip6_ptr)->addr_list))
+
+       in6_dev = __in6_dev_get(dev);
+       if (in6_dev && !list_empty(&in6_dev->addr_list))
                status |= ICMP_EXT_ECHOREPLY_IPV6;
+
        dev_put(dev);
        icmphdr->un.echo.sequence |= htons(status);
        return true;
index 1fe794967211e249016df00dc3c2ae230d71dcff..39229fd0601a11c3f2e58cd1e75db165a443b1a2 100644 (file)
@@ -1473,7 +1473,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
                 * by icmp_hdr(skb)->type.
                 */
                if (sk->sk_type == SOCK_RAW &&
-                   !inet_test_bit(HDRINCL, sk))
+                   !(fl4->flowi4_flags & FLOWI_FLAG_KNOWN_NH))
                        icmp_type = fl4->fl4_icmp_type;
                else
                        icmp_type = icmp_hdr(skb)->type;
index dcb11f22cbf2b437405d1b373dd0ebc37d02c9ec..4cb43401e0e06c5003c268c28bf0882ac4e8b4e0 100644 (file)
@@ -612,6 +612,9 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                            (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
                           daddr, saddr, 0, 0, sk->sk_uid);
 
+       fl4.fl4_icmp_type = 0;
+       fl4.fl4_icmp_code = 0;
+
        if (!hdrincl) {
                rfv.msg = msg;
                rfv.hlen = 0;
index d36ace160d426f6224f8e692f3b438ae863bb9b9..b814fdab19f710d066d323970be6ce57a3b583c5 100644 (file)
@@ -2166,6 +2166,9 @@ int ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        int err = -EINVAL;
        u32 tag = 0;
 
+       if (!in_dev)
+               return -EINVAL;
+
        if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr))
                goto martian_source;
 
index 3afeeb68e8a7e2a30ce9c4d92dcc8b150314b669..781b67a525719a42f21b713eb424427670d7afb2 100644 (file)
@@ -1068,6 +1068,7 @@ void tcp_ao_connect_init(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        struct tcp_ao_info *ao_info;
+       struct hlist_node *next;
        union tcp_ao_addr *addr;
        struct tcp_ao_key *key;
        int family, l3index;
@@ -1090,7 +1091,7 @@ void tcp_ao_connect_init(struct sock *sk)
        l3index = l3mdev_master_ifindex_by_index(sock_net(sk),
                                                 sk->sk_bound_dev_if);
 
-       hlist_for_each_entry_rcu(key, &ao_info->head, node) {
+       hlist_for_each_entry_safe(key, next, &ao_info->head, node) {
                if (!tcp_ao_key_cmp(key, l3index, addr, key->prefixlen, family, -1, -1))
                        continue;
 
index c02bf011d4a6f487b2c69e48e5032068eed3debc..b32cf2eeeb41d1fc0bbe24e4888301f344ec8488 100644 (file)
@@ -532,7 +532,8 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
 struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb,
                                 __be16 sport, __be16 dport)
 {
-       const struct iphdr *iph = ip_hdr(skb);
+       const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
+       const struct iphdr *iph = (struct iphdr *)(skb->data + offset);
        struct net *net = dev_net(skb->dev);
        int iif, sdif;
 
@@ -1123,16 +1124,17 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
        if (msg->msg_controllen) {
                err = udp_cmsg_send(sk, msg, &ipc.gso_size);
-               if (err > 0)
+               if (err > 0) {
                        err = ip_cmsg_send(sk, msg, &ipc,
                                           sk->sk_family == AF_INET6);
+                       connected = 0;
+               }
                if (unlikely(err < 0)) {
                        kfree(ipc.opt);
                        return err;
                }
                if (ipc.opt)
                        free = 1;
-               connected = 0;
        }
        if (!ipc.opt) {
                struct ip_options_rcu *inet_opt;
index 3498dd1d0694dc3ddb984177d2ddffb7b8abd0b9..8721fe5beca2bea692eb2cfa454e724e649cea6d 100644 (file)
@@ -471,6 +471,7 @@ static struct sk_buff *udp_gro_receive_segment(struct list_head *head,
        struct sk_buff *p;
        unsigned int ulen;
        int ret = 0;
+       int flush;
 
        /* requires non zero csum, for symmetry with GSO */
        if (!uh->check) {
@@ -504,13 +505,22 @@ static struct sk_buff *udp_gro_receive_segment(struct list_head *head,
                        return p;
                }
 
+               flush = NAPI_GRO_CB(p)->flush;
+
+               if (NAPI_GRO_CB(p)->flush_id != 1 ||
+                   NAPI_GRO_CB(p)->count != 1 ||
+                   !NAPI_GRO_CB(p)->is_atomic)
+                       flush |= NAPI_GRO_CB(p)->flush_id;
+               else
+                       NAPI_GRO_CB(p)->is_atomic = false;
+
                /* Terminate the flow on len mismatch or if it grow "too much".
                 * Under small packet flood GRO count could elsewhere grow a lot
                 * leading to excessive truesize values.
                 * On len mismatch merge the first packet shorter than gso_size,
                 * otherwise complete the GRO packet.
                 */
-               if (ulen > ntohs(uh2->len)) {
+               if (ulen > ntohs(uh2->len) || flush) {
                        pp = p;
                } else {
                        if (NAPI_GRO_CB(skb)->is_flist) {
@@ -718,7 +728,8 @@ EXPORT_SYMBOL(udp_gro_complete);
 
 INDIRECT_CALLABLE_SCOPE int udp4_gro_complete(struct sk_buff *skb, int nhoff)
 {
-       const struct iphdr *iph = ip_hdr(skb);
+       const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
+       const struct iphdr *iph = (struct iphdr *)(skb->data + offset);
        struct udphdr *uh = (struct udphdr *)(skb->data + nhoff);
 
        /* do fraglist only if there is no outer UDP encap (or we already processed it) */
index b41e35af69ea2835aa47d6ca01d9b109d4092462..c8b909a9904f321b91c9cfef46da9bb491c18a7d 100644 (file)
@@ -237,6 +237,7 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff *ipv6_gro_receive(struct list_head *head,
                goto out;
 
        skb_set_network_header(skb, off);
+       NAPI_GRO_CB(skb)->inner_network_offset = off;
 
        flush += ntohs(iph->payload_len) != skb->len - hlen;
 
index 8b1dd7f512491d806e4d0a9fc5297a255dafd5a4..8f7aa8bac1e7b1eb330e4a6a9086b88e509886be 100644 (file)
@@ -272,7 +272,8 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
 struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb,
                                 __be16 sport, __be16 dport)
 {
-       const struct ipv6hdr *iph = ipv6_hdr(skb);
+       const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
+       const struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + offset);
        struct net *net = dev_net(skb->dev);
        int iif, sdif;
 
@@ -1474,9 +1475,11 @@ do_udp_sendmsg:
                ipc6.opt = opt;
 
                err = udp_cmsg_send(sk, msg, &ipc6.gso_size);
-               if (err > 0)
+               if (err > 0) {
                        err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, fl6,
                                                    &ipc6);
+                       connected = false;
+               }
                if (err < 0) {
                        fl6_sock_release(flowlabel);
                        return err;
@@ -1488,7 +1491,6 @@ do_udp_sendmsg:
                }
                if (!(opt->opt_nflen|opt->opt_flen))
                        opt = NULL;
-               connected = false;
        }
        if (!opt) {
                opt = txopt_get(np);
index bbd347de00b450bb3ecbbfa41c4dab9d36bb79d9..b41152dd424697a9fc3cef13fbb430de49dcb913 100644 (file)
@@ -164,7 +164,8 @@ flush:
 
 INDIRECT_CALLABLE_SCOPE int udp6_gro_complete(struct sk_buff *skb, int nhoff)
 {
-       const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+       const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
+       const struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + offset);
        struct udphdr *uh = (struct udphdr *)(skb->data + nhoff);
 
        /* do fraglist only if there is no outer UDP encap (or we already processed it) */
index 39e487ccc46881b2ede597672b0e3df63ba8b05a..8ba00ad433c21bfc8f6566bed1360cb8e4cf4944 100644 (file)
@@ -127,6 +127,9 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb,
        /* checksums verified by L2TP */
        skb->ip_summed = CHECKSUM_NONE;
 
+       /* drop outer flow-hash */
+       skb_clear_hash(skb);
+
        skb_dst_drop(skb);
        nf_reset_ct(skb);
 
index 80e4b9784131d149c6acf27f79be0b0c16edec85..ccacaed32817aed59240034f85753c47a353501a 100644 (file)
@@ -797,6 +797,7 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_chanctx_conf *conf;
        struct ieee80211_chanctx *curr_ctx = NULL;
+       bool new_idle;
        int ret = 0;
 
        if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN))
@@ -829,8 +830,6 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
 out:
        rcu_assign_pointer(link->conf->chanctx_conf, conf);
 
-       sdata->vif.cfg.idle = !conf;
-
        if (curr_ctx && ieee80211_chanctx_num_assigned(local, curr_ctx) > 0) {
                ieee80211_recalc_chanctx_chantype(local, curr_ctx);
                ieee80211_recalc_smps_chanctx(local, curr_ctx);
@@ -843,9 +842,27 @@ out:
                ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL);
        }
 
-       if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
-           sdata->vif.type != NL80211_IFTYPE_MONITOR)
-               ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE);
+       if (conf) {
+               new_idle = false;
+       } else {
+               struct ieee80211_link_data *tmp;
+
+               new_idle = true;
+               for_each_sdata_link(local, tmp) {
+                       if (rcu_access_pointer(tmp->conf->chanctx_conf)) {
+                               new_idle = false;
+                               break;
+                       }
+               }
+       }
+
+       if (new_idle != sdata->vif.cfg.idle) {
+               sdata->vif.cfg.idle = new_idle;
+
+               if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
+                   sdata->vif.type != NL80211_IFTYPE_MONITOR)
+                       ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE);
+       }
 
        ieee80211_check_fast_xmit_iface(sdata);
 
index 32475da98d739cbe66d200f6bd8e8b0542f3cb04..cbc9b5e40cb35e81fb80dd55016c3afc8c31deb7 100644 (file)
@@ -747,6 +747,9 @@ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
                              struct sk_buff *skb, u32 ctrl_flags)
 {
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+       struct ieee80211_mesh_fast_tx_key key = {
+               .type = MESH_FAST_TX_TYPE_LOCAL
+       };
        struct ieee80211_mesh_fast_tx *entry;
        struct ieee80211s_hdr *meshhdr;
        u8 sa[ETH_ALEN] __aligned(2);
@@ -782,7 +785,10 @@ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
                        return false;
        }
 
-       entry = mesh_fast_tx_get(sdata, skb->data);
+       ether_addr_copy(key.addr, skb->data);
+       if (!ether_addr_equal(skb->data + ETH_ALEN, sdata->vif.addr))
+               key.type = MESH_FAST_TX_TYPE_PROXIED;
+       entry = mesh_fast_tx_get(sdata, &key);
        if (!entry)
                return false;
 
index d913ce7ba72ef897fb6857f55df3fb20bc871b5e..3f9664e4e00c6c2e51faaa43d1a23860a6d22e4c 100644 (file)
@@ -134,10 +134,39 @@ struct mesh_path {
 #define MESH_FAST_TX_CACHE_THRESHOLD_SIZE      384
 #define MESH_FAST_TX_CACHE_TIMEOUT             8000 /* msecs */
 
+/**
+ * enum ieee80211_mesh_fast_tx_type - cached mesh fast tx entry type
+ *
+ * @MESH_FAST_TX_TYPE_LOCAL: tx from the local vif address as SA
+ * @MESH_FAST_TX_TYPE_PROXIED: local tx with a different SA (e.g. bridged)
+ * @MESH_FAST_TX_TYPE_FORWARDED: forwarded from a different mesh point
+ * @NUM_MESH_FAST_TX_TYPE: number of entry types
+ */
+enum ieee80211_mesh_fast_tx_type {
+       MESH_FAST_TX_TYPE_LOCAL,
+       MESH_FAST_TX_TYPE_PROXIED,
+       MESH_FAST_TX_TYPE_FORWARDED,
+
+       /* must be last */
+       NUM_MESH_FAST_TX_TYPE
+};
+
+
+/**
+ * struct ieee80211_mesh_fast_tx_key - cached mesh fast tx entry key
+ *
+ * @addr: The Ethernet DA for this entry
+ * @type: cache entry type
+ */
+struct ieee80211_mesh_fast_tx_key {
+       u8 addr[ETH_ALEN] __aligned(2);
+       u16 type;
+};
+
 /**
  * struct ieee80211_mesh_fast_tx - cached mesh fast tx entry
  * @rhash: rhashtable pointer
- * @addr_key: The Ethernet DA which is the key for this entry
+ * @key: the lookup key for this cache entry
  * @fast_tx: base fast_tx data
  * @hdr: cached mesh and rfc1042 headers
  * @hdrlen: length of mesh + rfc1042
@@ -148,7 +177,7 @@ struct mesh_path {
  */
 struct ieee80211_mesh_fast_tx {
        struct rhash_head rhash;
-       u8 addr_key[ETH_ALEN] __aligned(2);
+       struct ieee80211_mesh_fast_tx_key key;
 
        struct ieee80211_fast_tx fast_tx;
        u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)];
@@ -334,7 +363,8 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
 
 bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
 struct ieee80211_mesh_fast_tx *
-mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr);
+mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_mesh_fast_tx_key *key);
 bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
                              struct sk_buff *skb, u32 ctrl_flags);
 void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
index 91b55d6a68b9739f9d22786bf403c801fc34d864..a6b62169f08483c5aa481f4f8f59f67fa56a4ef7 100644 (file)
@@ -37,8 +37,8 @@ static const struct rhashtable_params mesh_rht_params = {
 static const struct rhashtable_params fast_tx_rht_params = {
        .nelem_hint = 10,
        .automatic_shrinking = true,
-       .key_len = ETH_ALEN,
-       .key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key),
+       .key_len = sizeof_field(struct ieee80211_mesh_fast_tx, key),
+       .key_offset = offsetof(struct ieee80211_mesh_fast_tx, key),
        .head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash),
        .hashfn = mesh_table_hash,
 };
@@ -431,20 +431,21 @@ static void mesh_fast_tx_entry_free(struct mesh_tx_cache *cache,
 }
 
 struct ieee80211_mesh_fast_tx *
-mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr)
+mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_mesh_fast_tx_key *key)
 {
        struct ieee80211_mesh_fast_tx *entry;
        struct mesh_tx_cache *cache;
 
        cache = &sdata->u.mesh.tx_cache;
-       entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
+       entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
        if (!entry)
                return NULL;
 
        if (!(entry->mpath->flags & MESH_PATH_ACTIVE) ||
            mpath_expired(entry->mpath)) {
                spin_lock_bh(&cache->walk_lock);
-               entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
+               entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
                if (entry)
                    mesh_fast_tx_entry_free(cache, entry);
                spin_unlock_bh(&cache->walk_lock);
@@ -489,18 +490,24 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
        if (!sta)
                return;
 
+       build.key.type = MESH_FAST_TX_TYPE_LOCAL;
        if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
                /* This is required to keep the mppath alive */
                mppath = mpp_path_lookup(sdata, meshhdr->eaddr1);
                if (!mppath)
                        return;
                build.mppath = mppath;
+               if (!ether_addr_equal(meshhdr->eaddr2, sdata->vif.addr))
+                       build.key.type = MESH_FAST_TX_TYPE_PROXIED;
        } else if (ieee80211_has_a4(hdr->frame_control)) {
                mppath = mpath;
        } else {
                return;
        }
 
+       if (!ether_addr_equal(hdr->addr4, sdata->vif.addr))
+               build.key.type = MESH_FAST_TX_TYPE_FORWARDED;
+
        /* rate limit, in case fast xmit can't be enabled */
        if (mppath->fast_tx_check == jiffies)
                return;
@@ -547,7 +554,7 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
                }
        }
 
-       memcpy(build.addr_key, mppath->dst, ETH_ALEN);
+       memcpy(build.key.addr, mppath->dst, ETH_ALEN);
        build.timestamp = jiffies;
        build.fast_tx.band = info->band;
        build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3);
@@ -646,12 +653,18 @@ void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata,
                             const u8 *addr)
 {
        struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
+       struct ieee80211_mesh_fast_tx_key key = {};
        struct ieee80211_mesh_fast_tx *entry;
+       int i;
 
+       ether_addr_copy(key.addr, addr);
        spin_lock_bh(&cache->walk_lock);
-       entry = rhashtable_lookup_fast(&cache->rht, addr, fast_tx_rht_params);
-       if (entry)
-               mesh_fast_tx_entry_free(cache, entry);
+       for (i = 0; i < NUM_MESH_FAST_TX_TYPE; i++) {
+               key.type = i;
+               entry = rhashtable_lookup_fast(&cache->rht, &key, fast_tx_rht_params);
+               if (entry)
+                       mesh_fast_tx_entry_free(cache, entry);
+       }
        spin_unlock_bh(&cache->walk_lock);
 }
 
index 96b70006b7fc0b11b12f423fb74ec32a030d91af..3bbb216a0fc8ce58138420d13008b2240e260a77 100644 (file)
@@ -616,7 +616,6 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata,
                .from_ap = true,
                .start = ies->data,
                .len = ies->len,
-               .mode = conn->mode,
        };
        struct ieee802_11_elems *elems;
        struct ieee80211_supported_band *sband;
@@ -625,6 +624,7 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata,
        int ret;
 
 again:
+       parse_params.mode = conn->mode;
        elems = ieee802_11_parse_elems_full(&parse_params);
        if (!elems)
                return ERR_PTR(-ENOMEM);
@@ -632,15 +632,21 @@ again:
        ap_mode = ieee80211_determine_ap_chan(sdata, channel, bss->vht_cap_info,
                                              elems, false, conn, &ap_chandef);
 
-       mlme_link_id_dbg(sdata, link_id, "determined AP %pM to be %s\n",
-                        cbss->bssid, ieee80211_conn_mode_str(ap_mode));
-
        /* this should be impossible since parsing depends on our mode */
        if (WARN_ON(ap_mode > conn->mode)) {
                ret = -EINVAL;
                goto free;
        }
 
+       if (conn->mode != ap_mode) {
+               conn->mode = ap_mode;
+               kfree(elems);
+               goto again;
+       }
+
+       mlme_link_id_dbg(sdata, link_id, "determined AP %pM to be %s\n",
+                        cbss->bssid, ieee80211_conn_mode_str(ap_mode));
+
        sband = sdata->local->hw.wiphy->bands[channel->band];
 
        switch (channel->band) {
@@ -691,7 +697,6 @@ again:
                break;
        }
 
-       conn->mode = ap_mode;
        chanreq->oper = ap_chandef;
 
        /* wider-bandwidth OFDMA is only done in EHT */
@@ -753,8 +758,10 @@ again:
        }
 
        /* the mode can only decrease, so this must terminate */
-       if (ap_mode != conn->mode)
+       if (ap_mode != conn->mode) {
+               kfree(elems);
                goto again;
+       }
 
        mlme_link_id_dbg(sdata, link_id,
                         "connecting with %s mode, max bandwidth %d MHz\n",
@@ -5812,7 +5819,7 @@ static void ieee80211_ml_reconfiguration(struct ieee80211_sub_if_data *sdata,
                 */
                if (control &
                    IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT)
-                       link_removal_timeout[link_id] = le16_to_cpu(*(__le16 *)pos);
+                       link_removal_timeout[link_id] = get_unaligned_le16(pos);
        }
 
        removed_links &= sdata->vif.valid_links;
@@ -5837,8 +5844,11 @@ static void ieee80211_ml_reconfiguration(struct ieee80211_sub_if_data *sdata,
                        continue;
                }
 
-               link_delay = link_conf->beacon_int *
-                       link_removal_timeout[link_id];
+               if (link_removal_timeout[link_id] < 1)
+                       link_delay = 0;
+               else
+                       link_delay = link_conf->beacon_int *
+                               (link_removal_timeout[link_id] - 1);
 
                if (!delay)
                        delay = link_delay;
@@ -6193,7 +6203,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
                        link->u.mgd.dtim_period = elems->dtim_period;
                link->u.mgd.have_beacon = true;
                ifmgd->assoc_data->need_beacon = false;
-               if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
+               if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY) &&
+                   !ieee80211_is_s1g_beacon(hdr->frame_control)) {
                        link->conf->sync_tsf =
                                le64_to_cpu(mgmt->u.beacon.timestamp);
                        link->conf->sync_device_ts =
index 23404b275457a74868cd935653bc1a6192ec4cb5..4dc1def695486567b486fdada893557752f8df43 100644 (file)
@@ -877,6 +877,7 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_supported_band *sband;
+       u32 mask = ~0;
 
        rate_control_fill_sta_table(sta, info, dest, max_rates);
 
@@ -889,9 +890,12 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
        if (ieee80211_is_tx_data(skb))
                rate_control_apply_mask(sdata, sta, sband, dest, max_rates);
 
+       if (!(info->control.flags & IEEE80211_TX_CTRL_SCAN_TX))
+               mask = sdata->rc_rateidx_mask[info->band];
+
        if (dest[0].idx < 0)
                __rate_control_send_low(&sdata->local->hw, sband, sta, info,
-                                       sdata->rc_rateidx_mask[info->band]);
+                                       mask);
 
        if (sta)
                rate_fixup_ratelist(vif, sband, info, dest, max_rates);
index c1f8501384056d3ebbb9ba7ddbd5c659c579d582..6e24864f9a40ba1b8d689263cf905cc0ff5d3d69 100644 (file)
@@ -2763,7 +2763,10 @@ ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
                               struct sk_buff *skb, int hdrlen)
 {
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-       struct ieee80211_mesh_fast_tx *entry = NULL;
+       struct ieee80211_mesh_fast_tx_key key = {
+               .type = MESH_FAST_TX_TYPE_FORWARDED
+       };
+       struct ieee80211_mesh_fast_tx *entry;
        struct ieee80211s_hdr *mesh_hdr;
        struct tid_ampdu_tx *tid_tx;
        struct sta_info *sta;
@@ -2772,9 +2775,13 @@ ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
 
        mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth));
        if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
-               entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1);
+               ether_addr_copy(key.addr, mesh_hdr->eaddr1);
        else if (!(mesh_hdr->flags & MESH_FLAGS_AE))
-               entry = mesh_fast_tx_get(sdata, skb->data);
+               ether_addr_copy(key.addr, skb->data);
+       else
+               return false;
+
+       entry = mesh_fast_tx_get(sdata, &key);
        if (!entry)
                return false;
 
@@ -3780,6 +3787,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                }
                break;
        case WLAN_CATEGORY_PROTECTED_EHT:
+               if (len < offsetofend(typeof(*mgmt),
+                                     u.action.u.ttlm_req.action_code))
+                       break;
+
                switch (mgmt->u.action.u.ttlm_req.action_code) {
                case WLAN_PROTECTED_EHT_ACTION_TTLM_REQ:
                        if (sdata->vif.type != NL80211_IFTYPE_STATION)
index 0429e59ba387c931f42ae1e74255a7deb5ebf5d6..73850312580f7054c60550dd5a2486583ab48f0a 100644 (file)
@@ -648,6 +648,7 @@ static void ieee80211_send_scan_probe_req(struct ieee80211_sub_if_data *sdata,
                                cpu_to_le16(IEEE80211_SN_TO_SEQ(sn));
                }
                IEEE80211_SKB_CB(skb)->flags |= tx_flags;
+               IEEE80211_SKB_CB(skb)->control.flags |= IEEE80211_TX_CTRL_SCAN_TX;
                ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band);
        }
 }
index 6bf223e6cd1a54aa432ef0bd41da48cd9316ffc5..cfd0a62d0152bd28f32fbb022cdbd094defefca4 100644 (file)
@@ -698,11 +698,16 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
        txrc.bss_conf = &tx->sdata->vif.bss_conf;
        txrc.skb = tx->skb;
        txrc.reported_rate.idx = -1;
-       txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band];
 
-       if (tx->sdata->rc_has_mcs_mask[info->band])
-               txrc.rate_idx_mcs_mask =
-                       tx->sdata->rc_rateidx_mcs_mask[info->band];
+       if (unlikely(info->control.flags & IEEE80211_TX_CTRL_SCAN_TX)) {
+               txrc.rate_idx_mask = ~0;
+       } else {
+               txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band];
+
+               if (tx->sdata->rc_has_mcs_mask[info->band])
+                       txrc.rate_idx_mcs_mask =
+                               tx->sdata->rc_rateidx_mcs_mask[info->band];
+       }
 
        txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
                    tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
index 7e74b812e366ae311f52615e9b304d6fe8b924b8..965eb69dc5de32b0d0ec01e5270b20a4fcb436b3 100644 (file)
@@ -3723,6 +3723,9 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_TOKENFALLBACKINIT);
                mptcp_subflow_early_fallback(msk, subflow);
        }
+
+       WRITE_ONCE(msk->write_seq, subflow->idsn);
+       WRITE_ONCE(msk->snd_nxt, subflow->idsn);
        if (likely(!__mptcp_check_fallback(msk)))
                MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEACTIVE);
 
index a0921adc31a9ffe7db09d18e7ae54213a79a8fd7..1e689c71412716e04f417cdb62d9fb56b730a1ab 100644 (file)
@@ -126,7 +126,8 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
        if (sctph->source != cp->vport || payload_csum ||
            skb->ip_summed == CHECKSUM_PARTIAL) {
                sctph->source = cp->vport;
-               sctp_nat_csum(skb, sctph, sctphoff);
+               if (!skb_is_gso(skb) || !skb_is_gso_sctp(skb))
+                       sctp_nat_csum(skb, sctph, sctphoff);
        } else {
                skb->ip_summed = CHECKSUM_UNNECESSARY;
        }
@@ -174,7 +175,8 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
            (skb->ip_summed == CHECKSUM_PARTIAL &&
             !(skb_dst(skb)->dev->features & NETIF_F_SCTP_CRC))) {
                sctph->dest = cp->dport;
-               sctp_nat_csum(skb, sctph, sctphoff);
+               if (!skb_is_gso(skb) || !skb_is_gso_sctp(skb))
+                       sctp_nat_csum(skb, sctph, sctphoff);
        } else if (skb->ip_summed != CHECKSUM_PARTIAL) {
                skb->ip_summed = CHECKSUM_UNNECESSARY;
        }
index 9505f9d188ff257a8ca35f30ee111c2f19805a5a..6eef15648b7b0853fb249288bf4545dca3a2cf85 100644 (file)
@@ -21,7 +21,8 @@ nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb,
                proto = veth->h_vlan_encapsulated_proto;
                break;
        case htons(ETH_P_PPP_SES):
-               proto = nf_flow_pppoe_proto(skb);
+               if (!nf_flow_pppoe_proto(skb, &proto))
+                       return NF_ACCEPT;
                break;
        default:
                proto = skb->protocol;
index e45fade764096182443814e8dcd70700e7956742..5383bed3d3e002661f01468e1a8bef8425e229b4 100644 (file)
@@ -157,7 +157,7 @@ static void nf_flow_tuple_encap(struct sk_buff *skb,
                tuple->encap[i].proto = skb->protocol;
                break;
        case htons(ETH_P_PPP_SES):
-               phdr = (struct pppoe_hdr *)skb_mac_header(skb);
+               phdr = (struct pppoe_hdr *)skb_network_header(skb);
                tuple->encap[i].id = ntohs(phdr->sid);
                tuple->encap[i].proto = skb->protocol;
                break;
@@ -273,10 +273,11 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
        return NF_STOLEN;
 }
 
-static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto,
+static bool nf_flow_skb_encap_protocol(struct sk_buff *skb, __be16 proto,
                                       u32 *offset)
 {
        struct vlan_ethhdr *veth;
+       __be16 inner_proto;
 
        switch (skb->protocol) {
        case htons(ETH_P_8021Q):
@@ -287,7 +288,8 @@ static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto,
                }
                break;
        case htons(ETH_P_PPP_SES):
-               if (nf_flow_pppoe_proto(skb) == proto) {
+               if (nf_flow_pppoe_proto(skb, &inner_proto) &&
+                   inner_proto == proto) {
                        *offset += PPPOE_SES_HLEN;
                        return true;
                }
@@ -316,7 +318,7 @@ static void nf_flow_encap_pop(struct sk_buff *skb,
                        skb_reset_network_header(skb);
                        break;
                case htons(ETH_P_PPP_SES):
-                       skb->protocol = nf_flow_pppoe_proto(skb);
+                       skb->protocol = __nf_flow_pppoe_proto(skb);
                        skb_pull(skb, PPPOE_SES_HLEN);
                        skb_reset_network_header(skb);
                        break;
index d89d779467197a0846406e0b0ce6938e8a3d404d..167074283ea91dff50a7aa0299a5794bcddeb32a 100644 (file)
@@ -594,6 +594,12 @@ static int nft_mapelem_deactivate(const struct nft_ctx *ctx,
                                  const struct nft_set_iter *iter,
                                  struct nft_elem_priv *elem_priv)
 {
+       struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
+
+       if (!nft_set_elem_active(ext, iter->genmask))
+               return 0;
+
+       nft_set_elem_change_active(ctx->net, set, ext);
        nft_setelem_data_deactivate(ctx->net, set, elem_priv);
 
        return 0;
@@ -617,6 +623,7 @@ static void nft_map_catchall_deactivate(const struct nft_ctx *ctx,
                if (!nft_set_elem_active(ext, genmask))
                        continue;
 
+               nft_set_elem_change_active(ctx->net, set, ext);
                nft_setelem_data_deactivate(ctx->net, set, catchall->elem);
                break;
        }
@@ -626,6 +633,7 @@ static void nft_map_deactivate(const struct nft_ctx *ctx, struct nft_set *set)
 {
        struct nft_set_iter iter = {
                .genmask        = nft_genmask_next(ctx->net),
+               .type           = NFT_ITER_UPDATE,
                .fn             = nft_mapelem_deactivate,
        };
 
@@ -3060,7 +3068,7 @@ static const struct nft_expr_type *__nft_expr_type_get(u8 family,
 {
        const struct nft_expr_type *type, *candidate = NULL;
 
-       list_for_each_entry(type, &nf_tables_expressions, list) {
+       list_for_each_entry_rcu(type, &nf_tables_expressions, list) {
                if (!nla_strcmp(nla, type->name)) {
                        if (!type->family && !candidate)
                                candidate = type;
@@ -3092,9 +3100,13 @@ static const struct nft_expr_type *nft_expr_type_get(struct net *net,
        if (nla == NULL)
                return ERR_PTR(-EINVAL);
 
+       rcu_read_lock();
        type = __nft_expr_type_get(family, nla);
-       if (type != NULL && try_module_get(type->owner))
+       if (type != NULL && try_module_get(type->owner)) {
+               rcu_read_unlock();
                return type;
+       }
+       rcu_read_unlock();
 
        lockdep_nfnl_nft_mutex_not_held();
 #ifdef CONFIG_MODULES
@@ -3875,6 +3887,9 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
        const struct nft_data *data;
        int err;
 
+       if (!nft_set_elem_active(ext, iter->genmask))
+               return 0;
+
        if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
            *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END)
                return 0;
@@ -3898,17 +3913,20 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
 
 int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set)
 {
-       u8 genmask = nft_genmask_next(ctx->net);
+       struct nft_set_iter dummy_iter = {
+               .genmask        = nft_genmask_next(ctx->net),
+       };
        struct nft_set_elem_catchall *catchall;
+
        struct nft_set_ext *ext;
        int ret = 0;
 
        list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
                ext = nft_set_elem_ext(set, catchall->elem);
-               if (!nft_set_elem_active(ext, genmask))
+               if (!nft_set_elem_active(ext, dummy_iter.genmask))
                        continue;
 
-               ret = nft_setelem_validate(ctx, set, NULL, catchall->elem);
+               ret = nft_setelem_validate(ctx, set, &dummy_iter, catchall->elem);
                if (ret < 0)
                        return ret;
        }
@@ -5397,6 +5415,11 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
                                        const struct nft_set_iter *iter,
                                        struct nft_elem_priv *elem_priv)
 {
+       const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
+
+       if (!nft_set_elem_active(ext, iter->genmask))
+               return 0;
+
        return nft_setelem_data_validate(ctx, set, elem_priv);
 }
 
@@ -5441,6 +5464,7 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
                }
 
                iter.genmask    = nft_genmask_next(ctx->net);
+               iter.type       = NFT_ITER_UPDATE;
                iter.skip       = 0;
                iter.count      = 0;
                iter.err        = 0;
@@ -5488,6 +5512,13 @@ static int nft_mapelem_activate(const struct nft_ctx *ctx,
                                const struct nft_set_iter *iter,
                                struct nft_elem_priv *elem_priv)
 {
+       struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
+
+       /* called from abort path, reverse check to undo changes. */
+       if (nft_set_elem_active(ext, iter->genmask))
+               return 0;
+
+       nft_clear(ctx->net, ext);
        nft_setelem_data_activate(ctx->net, set, elem_priv);
 
        return 0;
@@ -5505,6 +5536,7 @@ static void nft_map_catchall_activate(const struct nft_ctx *ctx,
                if (!nft_set_elem_active(ext, genmask))
                        continue;
 
+               nft_clear(ctx->net, ext);
                nft_setelem_data_activate(ctx->net, set, catchall->elem);
                break;
        }
@@ -5514,6 +5546,7 @@ static void nft_map_activate(const struct nft_ctx *ctx, struct nft_set *set)
 {
        struct nft_set_iter iter = {
                .genmask        = nft_genmask_next(ctx->net),
+               .type           = NFT_ITER_UPDATE,
                .fn             = nft_mapelem_activate,
        };
 
@@ -5778,6 +5811,9 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
        const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
        struct nft_set_dump_args *args;
 
+       if (!nft_set_elem_active(ext, iter->genmask))
+               return 0;
+
        if (nft_set_elem_expired(ext) || nft_set_elem_is_dead(ext))
                return 0;
 
@@ -5888,6 +5924,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
        args.skb                = skb;
        args.reset              = dump_ctx->reset;
        args.iter.genmask       = nft_genmask_cur(net);
+       args.iter.type          = NFT_ITER_READ;
        args.iter.skip          = cb->args[0];
        args.iter.count         = 0;
        args.iter.err           = 0;
@@ -6627,7 +6664,7 @@ static void nft_setelem_activate(struct net *net, struct nft_set *set,
        struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
 
        if (nft_setelem_is_catchall(set, elem_priv)) {
-               nft_set_elem_change_active(net, set, ext);
+               nft_clear(net, ext);
        } else {
                set->ops->activate(net, set, elem_priv);
        }
@@ -7186,6 +7223,16 @@ void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
        }
 }
 
+static int nft_setelem_active_next(const struct net *net,
+                                  const struct nft_set *set,
+                                  struct nft_elem_priv *elem_priv)
+{
+       const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
+       u8 genmask = nft_genmask_next(net);
+
+       return nft_set_elem_active(ext, genmask);
+}
+
 static void nft_setelem_data_activate(const struct net *net,
                                      const struct nft_set *set,
                                      struct nft_elem_priv *elem_priv)
@@ -7309,8 +7356,12 @@ static int nft_setelem_flush(const struct nft_ctx *ctx,
                             const struct nft_set_iter *iter,
                             struct nft_elem_priv *elem_priv)
 {
+       const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
        struct nft_trans *trans;
 
+       if (!nft_set_elem_active(ext, iter->genmask))
+               return 0;
+
        trans = nft_trans_alloc_gfp(ctx, NFT_MSG_DELSETELEM,
                                    sizeof(struct nft_trans_elem), GFP_ATOMIC);
        if (!trans)
@@ -7372,6 +7423,7 @@ static int nft_set_flush(struct nft_ctx *ctx, struct nft_set *set, u8 genmask)
 {
        struct nft_set_iter iter = {
                .genmask        = genmask,
+               .type           = NFT_ITER_UPDATE,
                .fn             = nft_setelem_flush,
        };
 
@@ -7607,7 +7659,7 @@ static const struct nft_object_type *__nft_obj_type_get(u32 objtype, u8 family)
 {
        const struct nft_object_type *type;
 
-       list_for_each_entry(type, &nf_tables_objects, list) {
+       list_for_each_entry_rcu(type, &nf_tables_objects, list) {
                if (type->family != NFPROTO_UNSPEC &&
                    type->family != family)
                        continue;
@@ -7623,9 +7675,13 @@ nft_obj_type_get(struct net *net, u32 objtype, u8 family)
 {
        const struct nft_object_type *type;
 
+       rcu_read_lock();
        type = __nft_obj_type_get(objtype, family);
-       if (type != NULL && try_module_get(type->owner))
+       if (type != NULL && try_module_get(type->owner)) {
+               rcu_read_unlock();
                return type;
+       }
+       rcu_read_unlock();
 
        lockdep_nfnl_nft_mutex_not_held();
 #ifdef CONFIG_MODULES
@@ -10598,8 +10654,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
                case NFT_MSG_DESTROYSETELEM:
                        te = (struct nft_trans_elem *)trans->data;
 
-                       nft_setelem_data_activate(net, te->set, te->elem_priv);
-                       nft_setelem_activate(net, te->set, te->elem_priv);
+                       if (!nft_setelem_active_next(net, te->set, te->elem_priv)) {
+                               nft_setelem_data_activate(net, te->set, te->elem_priv);
+                               nft_setelem_activate(net, te->set, te->elem_priv);
+                       }
                        if (!nft_setelem_is_catchall(te->set, te->elem_priv))
                                te->set->ndeact--;
 
@@ -10787,6 +10845,9 @@ static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx,
 {
        const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
 
+       if (!nft_set_elem_active(ext, iter->genmask))
+               return 0;
+
        if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
            *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END)
                return 0;
@@ -10871,6 +10932,7 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx,
                                continue;
 
                        iter.genmask    = nft_genmask_next(ctx->net);
+                       iter.type       = NFT_ITER_UPDATE;
                        iter.skip       = 0;
                        iter.count      = 0;
                        iter.err        = 0;
index 274b6f7e6bb57e4f270262ef923ebf8d7f1cf02c..d170758a1eb5d08929cc4cd8e8acd350e793524e 100644 (file)
@@ -338,7 +338,9 @@ static void nft_netdev_event(unsigned long event, struct net_device *dev,
                return;
 
        if (n > 1) {
-               nf_unregister_net_hook(ctx->net, &found->ops);
+               if (!(ctx->chain->table->flags & NFT_TABLE_F_DORMANT))
+                       nf_unregister_net_hook(ctx->net, &found->ops);
+
                list_del_rcu(&found->list);
                kfree_rcu(found, rcu);
                return;
index a0055f510e31e9b77526a11c66c565b973897706..b314ca728a2912da717995840ef3dc337eace815 100644 (file)
@@ -216,6 +216,7 @@ static int nft_lookup_validate(const struct nft_ctx *ctx,
                return 0;
 
        iter.genmask    = nft_genmask_next(ctx->net);
+       iter.type       = NFT_ITER_UPDATE;
        iter.skip       = 0;
        iter.count      = 0;
        iter.err        = 0;
index 32df7a16835da3e1d850d34a8236e0a45f06f026..1caa04619dc6da37f845acc65c8ca86c173096de 100644 (file)
@@ -172,7 +172,7 @@ static void nft_bitmap_activate(const struct net *net,
        nft_bitmap_location(set, nft_set_ext_key(&be->ext), &idx, &off);
        /* Enter 11 state. */
        priv->bitmap[idx] |= (genmask << off);
-       nft_set_elem_change_active(net, set, &be->ext);
+       nft_clear(net, &be->ext);
 }
 
 static void nft_bitmap_flush(const struct net *net,
@@ -222,8 +222,6 @@ static void nft_bitmap_walk(const struct nft_ctx *ctx,
        list_for_each_entry_rcu(be, &priv->list, head) {
                if (iter->count < iter->skip)
                        goto cont;
-               if (!nft_set_elem_active(&be->ext, iter->genmask))
-                       goto cont;
 
                iter->err = iter->fn(ctx, set, iter, &be->priv);
 
index 6968a3b342367c6c0cb0df7523fdfd5864038802..daa56dda737ae2e6b4727c2d3930d68e58a33efb 100644 (file)
@@ -199,7 +199,7 @@ static void nft_rhash_activate(const struct net *net, const struct nft_set *set,
 {
        struct nft_rhash_elem *he = nft_elem_priv_cast(elem_priv);
 
-       nft_set_elem_change_active(net, set, &he->ext);
+       nft_clear(net, &he->ext);
 }
 
 static void nft_rhash_flush(const struct net *net,
@@ -286,8 +286,6 @@ static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set,
 
                if (iter->count < iter->skip)
                        goto cont;
-               if (!nft_set_elem_active(&he->ext, iter->genmask))
-                       goto cont;
 
                iter->err = iter->fn(ctx, set, iter, &he->priv);
                if (iter->err < 0)
@@ -599,7 +597,7 @@ static void nft_hash_activate(const struct net *net, const struct nft_set *set,
 {
        struct nft_hash_elem *he = nft_elem_priv_cast(elem_priv);
 
-       nft_set_elem_change_active(net, set, &he->ext);
+       nft_clear(net, &he->ext);
 }
 
 static void nft_hash_flush(const struct net *net,
@@ -652,8 +650,6 @@ static void nft_hash_walk(const struct nft_ctx *ctx, struct nft_set *set,
                hlist_for_each_entry_rcu(he, &priv->table[i], node) {
                        if (iter->count < iter->skip)
                                goto cont;
-                       if (!nft_set_elem_active(&he->ext, iter->genmask))
-                               goto cont;
 
                        iter->err = iter->fn(ctx, set, iter, &he->priv);
                        if (iter->err < 0)
index df8de50902463738642d4d24b59f12b17b5ff726..187138afac45d479f89ea23ec9b09fcd6b6da866 100644 (file)
@@ -1847,7 +1847,7 @@ static void nft_pipapo_activate(const struct net *net,
 {
        struct nft_pipapo_elem *e = nft_elem_priv_cast(elem_priv);
 
-       nft_set_elem_change_active(net, set, &e->ext);
+       nft_clear(net, &e->ext);
 }
 
 /**
@@ -2077,6 +2077,8 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set,
                rules_fx = rules_f0;
 
                nft_pipapo_for_each_field(f, i, m) {
+                       bool last = i == m->field_count - 1;
+
                        if (!pipapo_match_field(f, start, rules_fx,
                                                match_start, match_end))
                                break;
@@ -2089,16 +2091,18 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set,
 
                        match_start += NFT_PIPAPO_GROUPS_PADDED_SIZE(f);
                        match_end += NFT_PIPAPO_GROUPS_PADDED_SIZE(f);
-               }
 
-               if (i == m->field_count) {
-                       priv->dirty = true;
-                       pipapo_drop(m, rulemap);
-                       return;
+                       if (last && f->mt[rulemap[i].to].e == e) {
+                               priv->dirty = true;
+                               pipapo_drop(m, rulemap);
+                               return;
+                       }
                }
 
                first_rule += rules_f0;
        }
+
+       WARN_ON_ONCE(1); /* elem_priv not found */
 }
 
 /**
@@ -2115,13 +2119,15 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
                            struct nft_set_iter *iter)
 {
        struct nft_pipapo *priv = nft_set_priv(set);
-       struct net *net = read_pnet(&set->net);
        const struct nft_pipapo_match *m;
        const struct nft_pipapo_field *f;
        unsigned int i, r;
 
+       WARN_ON_ONCE(iter->type != NFT_ITER_READ &&
+                    iter->type != NFT_ITER_UPDATE);
+
        rcu_read_lock();
-       if (iter->genmask == nft_genmask_cur(net))
+       if (iter->type == NFT_ITER_READ)
                m = rcu_dereference(priv->match);
        else
                m = priv->clone;
@@ -2143,9 +2149,6 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
 
                e = f->mt[r].e;
 
-               if (!nft_set_elem_active(&e->ext, iter->genmask))
-                       goto cont;
-
                iter->err = iter->fn(ctx, set, iter, &e->priv);
                if (iter->err < 0)
                        goto out;
index 9944fe479e5361dc140f75be8b90bf3c5deb40f6..b7ea21327549b353c087b3e607e722f391ea94c1 100644 (file)
@@ -532,7 +532,7 @@ static void nft_rbtree_activate(const struct net *net,
 {
        struct nft_rbtree_elem *rbe = nft_elem_priv_cast(elem_priv);
 
-       nft_set_elem_change_active(net, set, &rbe->ext);
+       nft_clear(net, &rbe->ext);
 }
 
 static void nft_rbtree_flush(const struct net *net,
@@ -600,8 +600,6 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
 
                if (iter->count < iter->skip)
                        goto cont;
-               if (!nft_set_elem_active(&rbe->ext, iter->genmask))
-                       goto cont;
 
                iter->err = iter->fn(ctx, set, iter, &rbe->priv);
                if (iter->err < 0) {
index f4a38bd6a7e04f5944f8fa3d7f3cdc43caffed41..bfb7758063f315f4d13a6c17f8b01739933a6cf3 100644 (file)
@@ -77,13 +77,15 @@ EXPORT_SYMBOL_GPL(nsh_pop);
 static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
                                       netdev_features_t features)
 {
+       unsigned int outer_hlen, mac_len, nsh_len;
        struct sk_buff *segs = ERR_PTR(-EINVAL);
        u16 mac_offset = skb->mac_header;
-       unsigned int nsh_len, mac_len;
-       __be16 proto;
+       __be16 outer_proto, proto;
 
        skb_reset_network_header(skb);
 
+       outer_proto = skb->protocol;
+       outer_hlen = skb_mac_header_len(skb);
        mac_len = skb->mac_len;
 
        if (unlikely(!pskb_may_pull(skb, NSH_BASE_HDR_LEN)))
@@ -113,10 +115,10 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
        }
 
        for (skb = segs; skb; skb = skb->next) {
-               skb->protocol = htons(ETH_P_NSH);
-               __skb_push(skb, nsh_len);
-               skb->mac_header = mac_offset;
-               skb->network_header = skb->mac_header + mac_len;
+               skb->protocol = outer_proto;
+               __skb_push(skb, nsh_len + outer_hlen);
+               skb_reset_mac_header(skb);
+               skb_set_network_header(skb, outer_hlen);
                skb->mac_len = mac_len;
        }
 
index 74b63cdb59923a95dd03a9c2c540af702564873a..2928c142a2ddb3a0d9b1937fdb4ddd37322b3f45 100644 (file)
@@ -1593,9 +1593,9 @@ static void ovs_ct_limit_exit(struct net *net, struct ovs_net *ovs_net)
        for (i = 0; i < CT_LIMIT_HASH_BUCKETS; ++i) {
                struct hlist_head *head = &info->limits[i];
                struct ovs_ct_limit *ct_limit;
+               struct hlist_node *next;
 
-               hlist_for_each_entry_rcu(ct_limit, head, hlist_node,
-                                        lockdep_ovsl_is_held())
+               hlist_for_each_entry_safe(ct_limit, next, head, hlist_node)
                        kfree_rcu(ct_limit, rcu);
        }
        kfree(info->limits);
index 0af4642aeec4bcba890cfe0723b4ae001b378cf8..1539d315afe74ace265dd7ac32ffc7031d0b2323 100644 (file)
@@ -119,18 +119,13 @@ struct rxrpc_connection *rxrpc_find_client_connection_rcu(struct rxrpc_local *lo
        switch (srx->transport.family) {
        case AF_INET:
                if (peer->srx.transport.sin.sin_port !=
-                   srx->transport.sin.sin_port ||
-                   peer->srx.transport.sin.sin_addr.s_addr !=
-                   srx->transport.sin.sin_addr.s_addr)
+                   srx->transport.sin.sin_port)
                        goto not_found;
                break;
 #ifdef CONFIG_AF_RXRPC_IPV6
        case AF_INET6:
                if (peer->srx.transport.sin6.sin6_port !=
-                   srx->transport.sin6.sin6_port ||
-                   memcmp(&peer->srx.transport.sin6.sin6_addr,
-                          &srx->transport.sin6.sin6_addr,
-                          sizeof(struct in6_addr)) != 0)
+                   srx->transport.sin6.sin6_port)
                        goto not_found;
                break;
 #endif
index f2701068ed9e4ce48c52848901e983f21de459c7..6716c021a532e184e5e09e50c958e4128d9f97bf 100644 (file)
@@ -19,7 +19,7 @@ static int none_init_connection_security(struct rxrpc_connection *conn,
  */
 static struct rxrpc_txbuf *none_alloc_txbuf(struct rxrpc_call *call, size_t remain, gfp_t gfp)
 {
-       return rxrpc_alloc_data_txbuf(call, min_t(size_t, remain, RXRPC_JUMBO_DATALEN), 0, gfp);
+       return rxrpc_alloc_data_txbuf(call, min_t(size_t, remain, RXRPC_JUMBO_DATALEN), 1, gfp);
 }
 
 static int none_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
index f1a68270862db9715801594e754f48d7a77d822d..48a1475e6b0634cc806641f4d5a134684d1c56cf 100644 (file)
@@ -155,7 +155,7 @@ static struct rxrpc_txbuf *rxkad_alloc_txbuf(struct rxrpc_call *call, size_t rem
        switch (call->conn->security_level) {
        default:
                space = min_t(size_t, remain, RXRPC_JUMBO_DATALEN);
-               return rxrpc_alloc_data_txbuf(call, space, 0, gfp);
+               return rxrpc_alloc_data_txbuf(call, space, 1, gfp);
        case RXRPC_SECURITY_AUTH:
                shdr = sizeof(struct rxkad_level1_hdr);
                break;
index e0679658d9de0e62edd777cad0b7e4281cfe2384..c3913d8a50d340bff0636f144f6c65afbe755cdd 100644 (file)
@@ -21,20 +21,20 @@ struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_
 {
        struct rxrpc_wire_header *whdr;
        struct rxrpc_txbuf *txb;
-       size_t total, hoff = 0;
+       size_t total, hoff;
        void *buf;
 
        txb = kmalloc(sizeof(*txb), gfp);
        if (!txb)
                return NULL;
 
-       if (data_align)
-               hoff = round_up(sizeof(*whdr), data_align) - sizeof(*whdr);
+       hoff = round_up(sizeof(*whdr), data_align) - sizeof(*whdr);
        total = hoff + sizeof(*whdr) + data_size;
 
+       data_align = umax(data_align, L1_CACHE_BYTES);
        mutex_lock(&call->conn->tx_data_alloc_lock);
-       buf = __page_frag_alloc_align(&call->conn->tx_data_alloc, total, gfp,
-                                     ~(data_align - 1) & ~(L1_CACHE_BYTES - 1));
+       buf = page_frag_alloc_align(&call->conn->tx_data_alloc, total, gfp,
+                                   data_align);
        mutex_unlock(&call->conn->tx_data_alloc_lock);
        if (!buf) {
                kfree(txb);
index ff5336493777507242320d7e9214c637663f0734..4a2c763e2d116693469e6c8bd9ce0ed8f7f667d9 100644 (file)
@@ -974,6 +974,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
        sch->enqueue = ops->enqueue;
        sch->dequeue = ops->dequeue;
        sch->dev_queue = dev_queue;
+       sch->owner = -1;
        netdev_hold(dev, &sch->dev_tracker, GFP_KERNEL);
        refcount_set(&sch->refcnt, 1);
 
index f2a100c4c81f12e8ed91d0400938b53e3dd0dc46..40797114d50a49a4e10cb30c182f094fc8e7313d 100644 (file)
@@ -230,28 +230,6 @@ static void svc_rdma_write_info_free(struct svc_rdma_write_info *info)
        queue_work(svcrdma_wq, &info->wi_work);
 }
 
-/**
- * svc_rdma_write_chunk_release - Release Write chunk I/O resources
- * @rdma: controlling transport
- * @ctxt: Send context that is being released
- */
-void svc_rdma_write_chunk_release(struct svcxprt_rdma *rdma,
-                                 struct svc_rdma_send_ctxt *ctxt)
-{
-       struct svc_rdma_write_info *info;
-       struct svc_rdma_chunk_ctxt *cc;
-
-       while (!list_empty(&ctxt->sc_write_info_list)) {
-               info = list_first_entry(&ctxt->sc_write_info_list,
-                                       struct svc_rdma_write_info, wi_list);
-               list_del(&info->wi_list);
-
-               cc = &info->wi_cc;
-               svc_rdma_wake_send_waiters(rdma, cc->cc_sqecount);
-               svc_rdma_write_info_free(info);
-       }
-}
-
 /**
  * svc_rdma_reply_chunk_release - Release Reply chunk I/O resources
  * @rdma: controlling transport
@@ -308,11 +286,13 @@ static void svc_rdma_write_done(struct ib_cq *cq, struct ib_wc *wc)
        struct ib_cqe *cqe = wc->wr_cqe;
        struct svc_rdma_chunk_ctxt *cc =
                        container_of(cqe, struct svc_rdma_chunk_ctxt, cc_cqe);
+       struct svc_rdma_write_info *info =
+                       container_of(cc, struct svc_rdma_write_info, wi_cc);
 
        switch (wc->status) {
        case IB_WC_SUCCESS:
                trace_svcrdma_wc_write(&cc->cc_cid);
-               return;
+               break;
        case IB_WC_WR_FLUSH_ERR:
                trace_svcrdma_wc_write_flush(wc, &cc->cc_cid);
                break;
@@ -320,11 +300,12 @@ static void svc_rdma_write_done(struct ib_cq *cq, struct ib_wc *wc)
                trace_svcrdma_wc_write_err(wc, &cc->cc_cid);
        }
 
-       /* The RDMA Write has flushed, so the client won't get
-        * some of the outgoing RPC message. Signal the loss
-        * to the client by closing the connection.
-        */
-       svc_xprt_deferred_close(&rdma->sc_xprt);
+       svc_rdma_wake_send_waiters(rdma, cc->cc_sqecount);
+
+       if (unlikely(wc->status != IB_WC_SUCCESS))
+               svc_xprt_deferred_close(&rdma->sc_xprt);
+
+       svc_rdma_write_info_free(info);
 }
 
 /**
@@ -620,19 +601,13 @@ static int svc_rdma_xb_write(const struct xdr_buf *xdr, void *data)
        return xdr->len;
 }
 
-/* Link Write WRs for @chunk onto @sctxt's WR chain.
- */
-static int svc_rdma_prepare_write_chunk(struct svcxprt_rdma *rdma,
-                                       struct svc_rdma_send_ctxt *sctxt,
-                                       const struct svc_rdma_chunk *chunk,
-                                       const struct xdr_buf *xdr)
+static int svc_rdma_send_write_chunk(struct svcxprt_rdma *rdma,
+                                    const struct svc_rdma_chunk *chunk,
+                                    const struct xdr_buf *xdr)
 {
        struct svc_rdma_write_info *info;
        struct svc_rdma_chunk_ctxt *cc;
-       struct ib_send_wr *first_wr;
        struct xdr_buf payload;
-       struct list_head *pos;
-       struct ib_cqe *cqe;
        int ret;
 
        if (xdr_buf_subsegment(xdr, &payload, chunk->ch_position,
@@ -648,25 +623,10 @@ static int svc_rdma_prepare_write_chunk(struct svcxprt_rdma *rdma,
        if (ret != payload.len)
                goto out_err;
 
-       ret = -EINVAL;
-       if (unlikely(cc->cc_sqecount > rdma->sc_sq_depth))
-               goto out_err;
-
-       first_wr = sctxt->sc_wr_chain;
-       cqe = &cc->cc_cqe;
-       list_for_each(pos, &cc->cc_rwctxts) {
-               struct svc_rdma_rw_ctxt *rwc;
-
-               rwc = list_entry(pos, struct svc_rdma_rw_ctxt, rw_list);
-               first_wr = rdma_rw_ctx_wrs(&rwc->rw_ctx, rdma->sc_qp,
-                                          rdma->sc_port_num, cqe, first_wr);
-               cqe = NULL;
-       }
-       sctxt->sc_wr_chain = first_wr;
-       sctxt->sc_sqecount += cc->cc_sqecount;
-       list_add(&info->wi_list, &sctxt->sc_write_info_list);
-
        trace_svcrdma_post_write_chunk(&cc->cc_cid, cc->cc_sqecount);
+       ret = svc_rdma_post_chunk_ctxt(rdma, cc);
+       if (ret < 0)
+               goto out_err;
        return 0;
 
 out_err:
@@ -675,27 +635,25 @@ out_err:
 }
 
 /**
- * svc_rdma_prepare_write_list - Construct WR chain for sending Write list
+ * svc_rdma_send_write_list - Send all chunks on the Write list
  * @rdma: controlling RDMA transport
- * @write_pcl: Write list provisioned by the client
- * @sctxt: Send WR resources
+ * @rctxt: Write list provisioned by the client
  * @xdr: xdr_buf containing an RPC Reply message
  *
  * Returns zero on success, or a negative errno if one or more
  * Write chunks could not be sent.
  */
-int svc_rdma_prepare_write_list(struct svcxprt_rdma *rdma,
-                               const struct svc_rdma_pcl *write_pcl,
-                               struct svc_rdma_send_ctxt *sctxt,
-                               const struct xdr_buf *xdr)
+int svc_rdma_send_write_list(struct svcxprt_rdma *rdma,
+                            const struct svc_rdma_recv_ctxt *rctxt,
+                            const struct xdr_buf *xdr)
 {
        struct svc_rdma_chunk *chunk;
        int ret;
 
-       pcl_for_each_chunk(chunk, write_pcl) {
+       pcl_for_each_chunk(chunk, &rctxt->rc_write_pcl) {
                if (!chunk->ch_payload_length)
                        break;
-               ret = svc_rdma_prepare_write_chunk(rdma, sctxt, chunk, xdr);
+               ret = svc_rdma_send_write_chunk(rdma, chunk, xdr);
                if (ret < 0)
                        return ret;
        }
index dfca39abd16c8860ade9a8f3fc0be4bc023361cd..bb5436b719e05126e250596b61b39230204620c3 100644 (file)
@@ -142,7 +142,6 @@ svc_rdma_send_ctxt_alloc(struct svcxprt_rdma *rdma)
        ctxt->sc_send_wr.sg_list = ctxt->sc_sges;
        ctxt->sc_send_wr.send_flags = IB_SEND_SIGNALED;
        ctxt->sc_cqe.done = svc_rdma_wc_send;
-       INIT_LIST_HEAD(&ctxt->sc_write_info_list);
        ctxt->sc_xprt_buf = buffer;
        xdr_buf_init(&ctxt->sc_hdrbuf, ctxt->sc_xprt_buf,
                     rdma->sc_max_req_size);
@@ -228,7 +227,6 @@ static void svc_rdma_send_ctxt_release(struct svcxprt_rdma *rdma,
        struct ib_device *device = rdma->sc_cm_id->device;
        unsigned int i;
 
-       svc_rdma_write_chunk_release(rdma, ctxt);
        svc_rdma_reply_chunk_release(rdma, ctxt);
 
        if (ctxt->sc_page_count)
@@ -1015,8 +1013,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
        if (!p)
                goto put_ctxt;
 
-       ret = svc_rdma_prepare_write_list(rdma, &rctxt->rc_write_pcl, sctxt,
-                                         &rqstp->rq_res);
+       ret = svc_rdma_send_write_list(rdma, rctxt, &rqstp->rq_res);
        if (ret < 0)
                goto put_ctxt;
 
index bb9b747d58a1afac3619b80cff3e8196e36d96c3..ce18716491c8fed0cbe234f2044e3539c3bac6a3 100644 (file)
@@ -2664,6 +2664,7 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
                .xprtsec        = {
                        .policy         = RPC_XPRTSEC_NONE,
                },
+               .stats          = upper_clnt->cl_stats,
        };
        unsigned int pflags = current->flags;
        struct rpc_clnt *lower_clnt;
index 5c9fd4791c4ba1976f1d3d7fcb9ad458df1436f7..76284fc538ebdd38d52c879bd4fc58c84abc6371 100644 (file)
@@ -142,9 +142,9 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
        if (fragid == FIRST_FRAGMENT) {
                if (unlikely(head))
                        goto err;
-               *buf = NULL;
                if (skb_has_frag_list(frag) && __skb_linearize(frag))
                        goto err;
+               *buf = NULL;
                frag = skb_unshare(frag, GFP_ATOMIC);
                if (unlikely(!frag))
                        goto err;
@@ -156,6 +156,11 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
        if (!head)
                goto err;
 
+       /* Either the input skb ownership is transferred to headskb
+        * or the input skb is freed, clear the reference to avoid
+        * bad access on error path.
+        */
+       *buf = NULL;
        if (skb_try_coalesce(head, frag, &headstolen, &delta)) {
                kfree_skb_partial(frag, headstolen);
        } else {
@@ -179,7 +184,6 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
                *headbuf = NULL;
                return 1;
        }
-       *buf = NULL;
        return 0;
 err:
        kfree_skb(*buf);
index 762f424ff2d59c51ba176bc9dff81b499542fb5c..e5e47452308ab713032d58eedbff68bee9dc3a8d 100644 (file)
@@ -215,7 +215,7 @@ static inline struct sk_buff *tls_strp_msg(struct tls_sw_context_rx *ctx)
 
 static inline bool tls_strp_msg_ready(struct tls_sw_context_rx *ctx)
 {
-       return ctx->strp.msg_ready;
+       return READ_ONCE(ctx->strp.msg_ready);
 }
 
 static inline bool tls_strp_msg_mixed_decrypted(struct tls_sw_context_rx *ctx)
index ca1e0e198ceb452fac72dd48f22ea0a1dcddee6b..5df08d848b5c9c9cf36e21a78c7bc59f38a8f22b 100644 (file)
@@ -360,7 +360,7 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
        if (strp->stm.full_len && strp->stm.full_len == skb->len) {
                desc->count = 0;
 
-               strp->msg_ready = 1;
+               WRITE_ONCE(strp->msg_ready, 1);
                tls_rx_msg_ready(strp);
        }
 
@@ -528,7 +528,7 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
        if (!tls_strp_check_queue_ok(strp))
                return tls_strp_read_copy(strp, false);
 
-       strp->msg_ready = 1;
+       WRITE_ONCE(strp->msg_ready, 1);
        tls_rx_msg_ready(strp);
 
        return 0;
@@ -580,7 +580,7 @@ void tls_strp_msg_done(struct tls_strparser *strp)
        else
                tls_strp_flush_anchor_copy(strp);
 
-       strp->msg_ready = 0;
+       WRITE_ONCE(strp->msg_ready, 0);
        memset(&strp->stm, 0, sizeof(strp->stm));
 
        tls_strp_check_rcv(strp);
index d032eb5fa6df1eb7422fdf8a54de40bd4f0683ac..9a6ad5974dff5e855cbc0ba2a1f7837733420c5f 100644 (file)
@@ -2663,7 +2663,9 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
                                        WRITE_ONCE(u->oob_skb, NULL);
                                        consume_skb(skb);
                                }
-                       } else if (!(flags & MSG_PEEK)) {
+                       } else if (flags & MSG_PEEK) {
+                               skb = NULL;
+                       } else {
                                skb_unlink(skb, &sk->sk_receive_queue);
                                WRITE_ONCE(u->oob_skb, NULL);
                                if (!WARN_ON_ONCE(skb_unref(skb)))
@@ -2741,18 +2743,16 @@ redo:
                last = skb = skb_peek(&sk->sk_receive_queue);
                last_len = last ? last->len : 0;
 
+again:
 #if IS_ENABLED(CONFIG_AF_UNIX_OOB)
                if (skb) {
                        skb = manage_oob(skb, sk, flags, copied);
-                       if (!skb) {
+                       if (!skb && copied) {
                                unix_state_unlock(sk);
-                               if (copied)
-                                       break;
-                               goto redo;
+                               break;
                        }
                }
 #endif
-again:
                if (skb == NULL) {
                        if (copied >= target)
                                goto unlock;
index 6433a414acf8624a1d98727f4e309b7c040710b9..0104be9d4704563791b1c1558fcbf166649fee25 100644 (file)
@@ -299,7 +299,7 @@ static void __unix_gc(struct work_struct *work)
                        __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
 
                        if (sk->sk_state == TCP_LISTEN) {
-                               unix_state_lock(sk);
+                               unix_state_lock_nested(sk, U_LOCK_GC_LISTENER);
                                unix_state_unlock(sk);
                        }
                }
index b4edba6b0b7ba0bf3200c7ce966a3e286a6fdf24..30ff9a47081348d1b14d1db520aeedf9c9ffdd09 100644 (file)
@@ -14030,6 +14030,8 @@ static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
 error:
        for (i = 0; i < new_coalesce.n_rules; i++) {
                tmp_rule = &new_coalesce.rules[i];
+               if (!tmp_rule)
+                       continue;
                for (j = 0; j < tmp_rule->n_patterns; j++)
                        kfree(tmp_rule->patterns[j].mask);
                kfree(tmp_rule->patterns);
index cbbf347c6b2e099802b135266ca7fae59bd467f9..df013c98b80dfb0e06a86a78415e51d79cd76693 100644 (file)
@@ -1758,7 +1758,7 @@ TRACE_EVENT(rdev_return_void_tx_rx,
 
 DECLARE_EVENT_CLASS(tx_rx_evt,
        TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
-       TP_ARGS(wiphy, rx, tx),
+       TP_ARGS(wiphy, tx, rx),
        TP_STRUCT__entry(
                WIPHY_ENTRY
                __field(u32, tx)
@@ -1775,7 +1775,7 @@ DECLARE_EVENT_CLASS(tx_rx_evt,
 
 DEFINE_EVENT(tx_rx_evt, rdev_set_antenna,
        TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
-       TP_ARGS(wiphy, rx, tx)
+       TP_ARGS(wiphy, tx, rx)
 );
 
 DECLARE_EVENT_CLASS(wiphy_netdev_id_evt,
index 846e6ab9d5a9b660fd871a13c8f984260a1b105a..86a125c4243cb2e5eba7f906417be4602bd8b738 100644 (file)
@@ -175,7 +175,6 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
        mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \
        OBJTREE=$(abspath $(objtree)) \
        $(RUSTDOC) --test $(rust_flags) \
-               @$(objtree)/include/generated/rustc_cfg \
                -L$(objtree)/$(obj) --extern alloc --extern kernel \
                --extern build_error --extern macros \
                --extern bindings --extern uapi \
index 424257284d167b5caa23ed880353abbd7ef2de34..09004b56fb65c7aadcf857a41086159b6fa1f550 100644 (file)
@@ -1292,8 +1292,15 @@ impl_zeroable! {
     i8, i16, i32, i64, i128, isize,
     f32, f64,
 
-    // SAFETY: These are ZSTs, there is nothing to zero.
-    {<T: ?Sized>} PhantomData<T>, core::marker::PhantomPinned, Infallible, (),
+    // Note: do not add uninhabited types (such as `!` or `core::convert::Infallible`) to this list;
+    // creating an instance of an uninhabited type is immediate undefined behavior. For more on
+    // uninhabited/empty types, consult The Rustonomicon:
+    // <https://doc.rust-lang.org/stable/nomicon/exotic-sizes.html#empty-types>. The Rust Reference
+    // also has information on undefined behavior:
+    // <https://doc.rust-lang.org/stable/reference/behavior-considered-undefined.html>.
+    //
+    // SAFETY: These are inhabited ZSTs; there is nothing to zero and a valid value exists.
+    {<T: ?Sized>} PhantomData<T>, core::marker::PhantomPinned, (),
 
     // SAFETY: Type is allowed to take any value, including all zeros.
     {<T>} MaybeUninit<T>,
index be68d5e567b1a1f7a181e08586ed05f2ca008cd6..6858e2f8a3ed976ce644eb2f8ea4d9fbb40edc3b 100644 (file)
@@ -65,7 +65,7 @@ const __LOG_PREFIX: &[u8] = b"rust_kernel\0";
 /// The top level entrypoint to implementing a kernel module.
 ///
 /// For any teardown or cleanup operations, your type may implement [`Drop`].
-pub trait Module: Sized + Sync {
+pub trait Module: Sized + Sync + Send {
     /// Called at module initialization time.
     ///
     /// Use this method to perform whatever setup or registration your module
index 96e09c6e8530b4d108e6a664e93ab41436c797dc..265d0e1c13710a53a9f9d0b5af12b24402eb4741 100644 (file)
@@ -640,6 +640,10 @@ pub struct Registration {
     drivers: Pin<&'static mut [DriverVTable]>,
 }
 
+// SAFETY: The only action allowed in a `Registration` instance is dropping it, which is safe to do
+// from any thread because `phy_drivers_unregister` can be called from any thread context.
+unsafe impl Send for Registration {}
+
 impl Registration {
     /// Registers a PHY driver.
     pub fn register(
index f489f3157383239d81c0badd5085627d431e6c4c..520eae5fd792810069d8018d922f6c56c0bcc101 100644 (file)
@@ -35,18 +35,6 @@ use proc_macro::TokenStream;
 ///     author: "Rust for Linux Contributors",
 ///     description: "My very own kernel module!",
 ///     license: "GPL",
-///     params: {
-///        my_i32: i32 {
-///            default: 42,
-///            permissions: 0o000,
-///            description: "Example of i32",
-///        },
-///        writeable_i32: i32 {
-///            default: 42,
-///            permissions: 0o644,
-///            description: "Example of i32",
-///        },
-///    },
 /// }
 ///
 /// struct MyModule;
index 27979e582e4b943b963a88ee7cecdea4f345b83f..acd0393b509574b0989bedcf1ed244532ab63a29 100644 (file)
@@ -199,17 +199,6 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
             /// Used by the printing macros, e.g. [`info!`].
             const __LOG_PREFIX: &[u8] = b\"{name}\\0\";
 
-            /// The \"Rust loadable module\" mark.
-            //
-            // This may be best done another way later on, e.g. as a new modinfo
-            // key or a new section. For the moment, keep it simple.
-            #[cfg(MODULE)]
-            #[doc(hidden)]
-            #[used]
-            static __IS_RUST_MODULE: () = ();
-
-            static mut __MOD: Option<{type_}> = None;
-
             // SAFETY: `__this_module` is constructed by the kernel at load time and will not be
             // freed until the module is unloaded.
             #[cfg(MODULE)]
@@ -221,81 +210,132 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
                 kernel::ThisModule::from_ptr(core::ptr::null_mut())
             }};
 
-            // Loadable modules need to export the `{{init,cleanup}}_module` identifiers.
-            /// # Safety
-            ///
-            /// This function must not be called after module initialization, because it may be
-            /// freed after that completes.
-            #[cfg(MODULE)]
-            #[doc(hidden)]
-            #[no_mangle]
-            #[link_section = \".init.text\"]
-            pub unsafe extern \"C\" fn init_module() -> core::ffi::c_int {{
-                __init()
-            }}
-
-            #[cfg(MODULE)]
-            #[doc(hidden)]
-            #[no_mangle]
-            pub extern \"C\" fn cleanup_module() {{
-                __exit()
-            }}
+            // Double nested modules, since then nobody can access the public items inside.
+            mod __module_init {{
+                mod __module_init {{
+                    use super::super::{type_};
+
+                    /// The \"Rust loadable module\" mark.
+                    //
+                    // This may be best done another way later on, e.g. as a new modinfo
+                    // key or a new section. For the moment, keep it simple.
+                    #[cfg(MODULE)]
+                    #[doc(hidden)]
+                    #[used]
+                    static __IS_RUST_MODULE: () = ();
+
+                    static mut __MOD: Option<{type_}> = None;
+
+                    // Loadable modules need to export the `{{init,cleanup}}_module` identifiers.
+                    /// # Safety
+                    ///
+                    /// This function must not be called after module initialization, because it may be
+                    /// freed after that completes.
+                    #[cfg(MODULE)]
+                    #[doc(hidden)]
+                    #[no_mangle]
+                    #[link_section = \".init.text\"]
+                    pub unsafe extern \"C\" fn init_module() -> core::ffi::c_int {{
+                        // SAFETY: This function is inaccessible to the outside due to the double
+                        // module wrapping it. It is called exactly once by the C side via its
+                        // unique name.
+                        unsafe {{ __init() }}
+                    }}
 
-            // Built-in modules are initialized through an initcall pointer
-            // and the identifiers need to be unique.
-            #[cfg(not(MODULE))]
-            #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))]
-            #[doc(hidden)]
-            #[link_section = \"{initcall_section}\"]
-            #[used]
-            pub static __{name}_initcall: extern \"C\" fn() -> core::ffi::c_int = __{name}_init;
+                    #[cfg(MODULE)]
+                    #[doc(hidden)]
+                    #[no_mangle]
+                    pub extern \"C\" fn cleanup_module() {{
+                        // SAFETY:
+                        // - This function is inaccessible to the outside due to the double
+                        //   module wrapping it. It is called exactly once by the C side via its
+                        //   unique name,
+                        // - furthermore it is only called after `init_module` has returned `0`
+                        //   (which delegates to `__init`).
+                        unsafe {{ __exit() }}
+                    }}
 
-            #[cfg(not(MODULE))]
-            #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)]
-            core::arch::global_asm!(
-                r#\".section \"{initcall_section}\", \"a\"
-                __{name}_initcall:
-                    .long   __{name}_init - .
-                    .previous
-                \"#
-            );
+                    // Built-in modules are initialized through an initcall pointer
+                    // and the identifiers need to be unique.
+                    #[cfg(not(MODULE))]
+                    #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))]
+                    #[doc(hidden)]
+                    #[link_section = \"{initcall_section}\"]
+                    #[used]
+                    pub static __{name}_initcall: extern \"C\" fn() -> core::ffi::c_int = __{name}_init;
+
+                    #[cfg(not(MODULE))]
+                    #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)]
+                    core::arch::global_asm!(
+                        r#\".section \"{initcall_section}\", \"a\"
+                        __{name}_initcall:
+                            .long   __{name}_init - .
+                            .previous
+                        \"#
+                    );
+
+                    #[cfg(not(MODULE))]
+                    #[doc(hidden)]
+                    #[no_mangle]
+                    pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{
+                        // SAFETY: This function is inaccessible to the outside due to the double
+                        // module wrapping it. It is called exactly once by the C side via its
+                        // placement above in the initcall section.
+                        unsafe {{ __init() }}
+                    }}
 
-            #[cfg(not(MODULE))]
-            #[doc(hidden)]
-            #[no_mangle]
-            pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{
-                __init()
-            }}
+                    #[cfg(not(MODULE))]
+                    #[doc(hidden)]
+                    #[no_mangle]
+                    pub extern \"C\" fn __{name}_exit() {{
+                        // SAFETY:
+                        // - This function is inaccessible to the outside due to the double
+                        //   module wrapping it. It is called exactly once by the C side via its
+                        //   unique name,
+                        // - furthermore it is only called after `__{name}_init` has returned `0`
+                        //   (which delegates to `__init`).
+                        unsafe {{ __exit() }}
+                    }}
 
-            #[cfg(not(MODULE))]
-            #[doc(hidden)]
-            #[no_mangle]
-            pub extern \"C\" fn __{name}_exit() {{
-                __exit()
-            }}
+                    /// # Safety
+                    ///
+                    /// This function must only be called once.
+                    unsafe fn __init() -> core::ffi::c_int {{
+                        match <{type_} as kernel::Module>::init(&super::super::THIS_MODULE) {{
+                            Ok(m) => {{
+                                // SAFETY: No data race, since `__MOD` can only be accessed by this
+                                // module and there only `__init` and `__exit` access it. These
+                                // functions are only called once and `__exit` cannot be called
+                                // before or during `__init`.
+                                unsafe {{
+                                    __MOD = Some(m);
+                                }}
+                                return 0;
+                            }}
+                            Err(e) => {{
+                                return e.to_errno();
+                            }}
+                        }}
+                    }}
 
-            fn __init() -> core::ffi::c_int {{
-                match <{type_} as kernel::Module>::init(&THIS_MODULE) {{
-                    Ok(m) => {{
+                    /// # Safety
+                    ///
+                    /// This function must
+                    /// - only be called once,
+                    /// - be called after `__init` has been called and returned `0`.
+                    unsafe fn __exit() {{
+                        // SAFETY: No data race, since `__MOD` can only be accessed by this module
+                        // and there only `__init` and `__exit` access it. These functions are only
+                        // called once and `__init` was already called.
                         unsafe {{
-                            __MOD = Some(m);
+                            // Invokes `drop()` on `__MOD`, which should be used for cleanup.
+                            __MOD = None;
                         }}
-                        return 0;
-                    }}
-                    Err(e) => {{
-                        return e.to_errno();
                     }}
-                }}
-            }}
 
-            fn __exit() {{
-                unsafe {{
-                    // Invokes `drop()` on `__MOD`, which should be used for cleanup.
-                    __MOD = None;
+                    {modinfo}
                 }}
             }}
-
-            {modinfo}
         ",
         type_ = info.type_,
         name = info.name,
index baf86c0880b6d7d548f4a6a21cd6305acc717078..533a7799fdfe6d1848ab6c5c6f7ef67990f8c9b0 100644 (file)
@@ -273,7 +273,7 @@ rust_common_cmd = \
        -Zallow-features=$(rust_allowed_features) \
        -Zcrate-attr=no_std \
        -Zcrate-attr='feature($(rust_allowed_features))' \
-       --extern alloc --extern kernel \
+       -Zunstable-options --extern force:alloc --extern kernel \
        --crate-type rlib -L $(objtree)/rust/ \
        --crate-name $(basename $(notdir $@)) \
        --sysroot=/dev/null \
index b141024830ecc831430c697858ce409a56c711af..ee6ac649df836d695133f93da9cfd0518cc1ae23 100644 (file)
@@ -428,7 +428,7 @@ static int cvt_ump_midi2_to_midi1(struct snd_seq_client *dest,
        midi1->note.group = midi2->note.group;
        midi1->note.status = midi2->note.status;
        midi1->note.channel = midi2->note.channel;
-       switch (midi2->note.status << 4) {
+       switch (midi2->note.status) {
        case UMP_MSG_STATUS_NOTE_ON:
        case UMP_MSG_STATUS_NOTE_OFF:
                midi1->note.note = midi2->note.note;
index 6a384b922e4fada5bfed7fa8b7e0f95ea7e3457a..d1f6cdcf1866e4162286b32072f7a21dc93ea94f 100644 (file)
@@ -557,9 +557,32 @@ static const struct config_entry *snd_intel_dsp_find_config
                if (table->codec_hid) {
                        int i;
 
-                       for (i = 0; i < table->codec_hid->num_codecs; i++)
-                               if (acpi_dev_present(table->codec_hid->codecs[i], NULL, -1))
+                       for (i = 0; i < table->codec_hid->num_codecs; i++) {
+                               struct nhlt_acpi_table *nhlt;
+                               bool ssp_found = false;
+
+                               if (!acpi_dev_present(table->codec_hid->codecs[i], NULL, -1))
+                                       continue;
+
+                               nhlt = intel_nhlt_init(&pci->dev);
+                               if (!nhlt) {
+                                       dev_warn(&pci->dev, "%s: NHLT table not found, skipped HID %s\n",
+                                                __func__, table->codec_hid->codecs[i]);
+                                       continue;
+                               }
+
+                               if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_SSP) &&
+                                   intel_nhlt_ssp_endpoint_mask(nhlt, NHLT_DEVICE_I2S))
+                                       ssp_found = true;
+
+                               intel_nhlt_free(nhlt);
+
+                               if (ssp_found)
                                        break;
+
+                               dev_warn(&pci->dev, "%s: no valid SSP found for HID %s, skipped\n",
+                                        __func__, table->codec_hid->codecs[i]);
+                       }
                        if (i == table->codec_hid->num_codecs)
                                continue;
                }
index 5f60658c6051c90bf06b42c8d39a53e3dd54c1f1..d7417a40392b2dc02647ff3ffb0802cfada6fa35 100644 (file)
@@ -45,6 +45,8 @@ static bool is_link_enabled(struct fwnode_handle *fw_node, u8 idx)
                                 "intel-quirk-mask",
                                 &quirk_mask);
 
+       fwnode_handle_put(link);
+
        if (quirk_mask & SDW_INTEL_QUIRK_MASK_BUS_DISABLE)
                return false;
 
index fe72e7d7724127418b0b5351e64f6dc0d8b2c831..dadeda7758ceebce94d6205d38b0807b1e6c5587 100644 (file)
@@ -189,8 +189,7 @@ static int snd_emu10k1_suspend(struct device *dev)
 
        emu->suspend = 1;
 
-       cancel_work_sync(&emu->emu1010.firmware_work);
-       cancel_work_sync(&emu->emu1010.clock_work);
+       cancel_work_sync(&emu->emu1010.work);
 
        snd_ac97_suspend(emu->ac97);
 
index de5c41e578e1f4ac3cf085f1c8b20c75a545fce8..8ccc0178360ce8c0a5d70b920d212ca299310fd6 100644 (file)
@@ -732,69 +732,67 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock,
        return snd_emu1010_load_firmware_entry(emu, *fw);
 }
 
-static void emu1010_firmware_work(struct work_struct *work)
+static void snd_emu1010_load_dock_firmware(struct snd_emu10k1 *emu)
 {
-       struct snd_emu10k1 *emu;
-       u32 tmp, tmp2, reg;
+       u32 tmp, tmp2;
        int err;
 
-       emu = container_of(work, struct snd_emu10k1,
-                          emu1010.firmware_work);
-       if (emu->card->shutdown)
+       // The docking events clearly arrive prematurely - while the
+       // Dock's FPGA seems to be successfully programmed, the Dock
+       // fails to initialize subsequently if we don't give it some
+       // time to "warm up" here.
+       msleep(200);
+
+       dev_info(emu->card->dev, "emu1010: Loading Audio Dock Firmware\n");
+       /* Return to Audio Dock programming mode */
+       snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG,
+                              EMU_HANA_FPGA_CONFIG_AUDIODOCK);
+       err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
+       if (err < 0)
                return;
-#ifdef CONFIG_PM_SLEEP
-       if (emu->suspend)
+       snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
+
+       snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
+       dev_dbg(emu->card->dev, "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp);
+       if ((tmp & 0x1f) != 0x15) {
+               /* FPGA failed to be programmed */
+               dev_err(emu->card->dev,
+                       "emu1010: Loading Audio Dock Firmware failed, reg = 0x%x\n",
+                       tmp);
                return;
-#endif
+       }
+       dev_info(emu->card->dev, "emu1010: Audio Dock Firmware loaded\n");
+
+       snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
+       snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
+       dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2);
+
+       /* Allow DLL to settle, to sync clocking between 1010 and Dock */
+       msleep(10);
+}
+
+static void emu1010_dock_event(struct snd_emu10k1 *emu)
+{
+       u32 reg;
+
        snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */
        if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) {
                /* Audio Dock attached */
-               /* Return to Audio Dock programming mode */
-               dev_info(emu->card->dev,
-                        "emu1010: Loading Audio Dock Firmware\n");
-               snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG,
-                                      EMU_HANA_FPGA_CONFIG_AUDIODOCK);
-               err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
-               if (err < 0)
-                       return;
-               snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
-               snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
-               dev_info(emu->card->dev,
-                        "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp);
-               if ((tmp & 0x1f) != 0x15) {
-                       /* FPGA failed to be programmed */
-                       dev_info(emu->card->dev,
-                                "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n",
-                                tmp);
-                       return;
-               }
-               dev_info(emu->card->dev,
-                        "emu1010: Audio Dock Firmware loaded\n");
-               snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
-               snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
-               dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2);
-               /* Sync clocking between 1010 and Dock */
-               /* Allow DLL to settle */
-               msleep(10);
+               snd_emu1010_load_dock_firmware(emu);
                /* Unmute all. Default is muted after a firmware load */
                snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
+       } else if (!(reg & EMU_HANA_OPTION_DOCK_ONLINE)) {
+               /* Audio Dock removed */
+               dev_info(emu->card->dev, "emu1010: Audio Dock detached\n");
+               /* The hardware auto-mutes all, so we unmute again */
+               snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
        }
 }
 
-static void emu1010_clock_work(struct work_struct *work)
+static void emu1010_clock_event(struct snd_emu10k1 *emu)
 {
-       struct snd_emu10k1 *emu;
        struct snd_ctl_elem_id id;
 
-       emu = container_of(work, struct snd_emu10k1,
-                          emu1010.clock_work);
-       if (emu->card->shutdown)
-               return;
-#ifdef CONFIG_PM_SLEEP
-       if (emu->suspend)
-               return;
-#endif
-
        spin_lock_irq(&emu->reg_lock);
        // This is the only thing that can actually happen.
        emu->emu1010.clock_source = emu->emu1010.clock_fallback;
@@ -805,21 +803,44 @@ static void emu1010_clock_work(struct work_struct *work)
        snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
 }
 
-static void emu1010_interrupt(struct snd_emu10k1 *emu)
+static void emu1010_work(struct work_struct *work)
 {
+       struct snd_emu10k1 *emu;
        u32 sts;
 
+       emu = container_of(work, struct snd_emu10k1, emu1010.work);
+       if (emu->card->shutdown)
+               return;
+#ifdef CONFIG_PM_SLEEP
+       if (emu->suspend)
+               return;
+#endif
+
+       snd_emu1010_fpga_lock(emu);
+
        snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &sts);
-       if (sts & EMU_HANA_IRQ_DOCK_LOST) {
-               /* Audio Dock removed */
-               dev_info(emu->card->dev, "emu1010: Audio Dock detached\n");
-               /* The hardware auto-mutes all, so we unmute again */
-               snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
-       } else if (sts & EMU_HANA_IRQ_DOCK) {
-               schedule_work(&emu->emu1010.firmware_work);
-       }
+
+       // The distinction of the IRQ status bits is unreliable,
+       // so we dispatch later based on option card status.
+       if (sts & (EMU_HANA_IRQ_DOCK | EMU_HANA_IRQ_DOCK_LOST))
+               emu1010_dock_event(emu);
+
        if (sts & EMU_HANA_IRQ_WCLK_CHANGED)
-               schedule_work(&emu->emu1010.clock_work);
+               emu1010_clock_event(emu);
+
+       snd_emu1010_fpga_unlock(emu);
+}
+
+static void emu1010_interrupt(struct snd_emu10k1 *emu)
+{
+       // We get an interrupt on each GPIO input pin change, but we
+       // care only about the ones triggered by the dedicated pin.
+       u16 sts = inw(emu->port + A_GPIO);
+       u16 bit = emu->card_capabilities->ca0108_chip ? 0x2000 : 0x8000;
+       if (!(sts & bit))
+               return;
+
+       schedule_work(&emu->emu1010.work);
 }
 
 /*
@@ -841,6 +862,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
         * Proper init follows in snd_emu10k1_init(). */
        outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG);
 
+       snd_emu1010_fpga_lock(emu);
+
        /* Disable 48Volt power to Audio Dock */
        snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
 
@@ -866,7 +889,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
        err = snd_emu1010_load_firmware(emu, 0, &emu->firmware);
        if (err < 0) {
                dev_info(emu->card->dev, "emu1010: Loading Firmware failed\n");
-               return err;
+               goto fail;
        }
 
        /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
@@ -876,7 +899,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
                dev_info(emu->card->dev,
                         "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n",
                         reg);
-               return -ENODEV;
+               err = -ENODEV;
+               goto fail;
        }
 
        dev_info(emu->card->dev, "emu1010: Hana Firmware loaded\n");
@@ -889,7 +913,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
        snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
        dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg);
        if (reg & EMU_HANA_OPTION_DOCK_OFFLINE)
-               schedule_work(&emu->emu1010.firmware_work);
+               snd_emu1010_load_dock_firmware(emu);
        if (emu->card_capabilities->no_adat) {
                emu->emu1010.optical_in = 0; /* IN_SPDIF */
                emu->emu1010.optical_out = 0; /* OUT_SPDIF */
@@ -936,7 +960,9 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
        // so it is safe to simply enable the outputs.
        snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
 
-       return 0;
+fail:
+       snd_emu1010_fpga_unlock(emu);
+       return err;
 }
 /*
  *  Create the EMU10K1 instance
@@ -958,10 +984,10 @@ static void snd_emu10k1_free(struct snd_card *card)
        }
        if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) {
                /* Disable 48Volt power to Audio Dock */
-               snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
+               snd_emu1010_fpga_write_lock(emu, EMU_HANA_DOCK_PWR, 0);
        }
-       cancel_work_sync(&emu->emu1010.firmware_work);
-       cancel_work_sync(&emu->emu1010.clock_work);
+       cancel_work_sync(&emu->emu1010.work);
+       mutex_destroy(&emu->emu1010.lock);
        release_firmware(emu->firmware);
        release_firmware(emu->dock_fw);
        snd_util_memhdr_free(emu->memhdr);
@@ -1540,8 +1566,8 @@ int snd_emu10k1_create(struct snd_card *card,
        emu->irq = -1;
        emu->synth = NULL;
        emu->get_synth_voice = NULL;
-       INIT_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work);
-       INIT_WORK(&emu->emu1010.clock_work, emu1010_clock_work);
+       INIT_WORK(&emu->emu1010.work, emu1010_work);
+       mutex_init(&emu->emu1010.lock);
        /* read revision & serial */
        emu->revision = pci->revision;
        pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
index 0a32ea53d8c648a78f44227579a76c5e111eda89..05b98d9b547b2a9ffd063649311887693b1b20de 100644 (file)
@@ -661,7 +661,9 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
        change = (emu->emu1010.output_source[channel] != val);
        if (change) {
                emu->emu1010.output_source[channel] = val;
+               snd_emu1010_fpga_lock(emu);
                snd_emu1010_output_source_apply(emu, channel, val);
+               snd_emu1010_fpga_unlock(emu);
        }
        return change;
 }
@@ -705,7 +707,9 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
        change = (emu->emu1010.input_source[channel] != val);
        if (change) {
                emu->emu1010.input_source[channel] = val;
+               snd_emu1010_fpga_lock(emu);
                snd_emu1010_input_source_apply(emu, channel, val);
+               snd_emu1010_fpga_unlock(emu);
        }
        return change;
 }
@@ -774,7 +778,7 @@ static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
                cache = cache & ~mask;
        change = (cache != emu->emu1010.adc_pads);
        if (change) {
-               snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );
+               snd_emu1010_fpga_write_lock(emu, EMU_HANA_ADC_PADS, cache );
                emu->emu1010.adc_pads = cache;
        }
 
@@ -832,7 +836,7 @@ static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
                cache = cache & ~mask;
        change = (cache != emu->emu1010.dac_pads);
        if (change) {
-               snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache );
+               snd_emu1010_fpga_write_lock(emu, EMU_HANA_DAC_PADS, cache );
                emu->emu1010.dac_pads = cache;
        }
 
@@ -980,6 +984,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol,
        val = ucontrol->value.enumerated.item[0] ;
        if (val >= emu_ci->num)
                return -EINVAL;
+       snd_emu1010_fpga_lock(emu);
        spin_lock_irq(&emu->reg_lock);
        change = (emu->emu1010.clock_source != val);
        if (change) {
@@ -996,6 +1001,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol,
        } else {
                spin_unlock_irq(&emu->reg_lock);
        }
+       snd_emu1010_fpga_unlock(emu);
        return change;
 }
 
@@ -1041,7 +1047,7 @@ static int snd_emu1010_clock_fallback_put(struct snd_kcontrol *kcontrol,
        change = (emu->emu1010.clock_fallback != val);
        if (change) {
                emu->emu1010.clock_fallback = val;
-               snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 1 - val);
+               snd_emu1010_fpga_write_lock(emu, EMU_HANA_DEFCLOCK, 1 - val);
        }
        return change;
 }
@@ -1093,7 +1099,7 @@ static int snd_emu1010_optical_out_put(struct snd_kcontrol *kcontrol,
                emu->emu1010.optical_out = val;
                tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) |
                        (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF);
-               snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
+               snd_emu1010_fpga_write_lock(emu, EMU_HANA_OPTICAL_TYPE, tmp);
        }
        return change;
 }
@@ -1144,7 +1150,7 @@ static int snd_emu1010_optical_in_put(struct snd_kcontrol *kcontrol,
                emu->emu1010.optical_in = val;
                tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) |
                        (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF);
-               snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
+               snd_emu1010_fpga_write_lock(emu, EMU_HANA_OPTICAL_TYPE, tmp);
        }
        return change;
 }
@@ -2323,7 +2329,9 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
                for (i = 0; i < emu_ri->n_outs; i++)
                        emu->emu1010.output_source[i] =
                                emu1010_map_source(emu_ri, emu_ri->out_dflts[i]);
+               snd_emu1010_fpga_lock(emu);
                snd_emu1010_apply_sources(emu);
+               snd_emu1010_fpga_unlock(emu);
 
                kctl = emu->ctl_clock_source = snd_ctl_new1(&snd_emu1010_clock_source, emu);
                err = snd_ctl_add(card, kctl);
index 2f80fd91017c3994e40017f9a9bb5c22ea21603a..737c28d31b41a39a4ca1ddb335df6b907c8e8a30 100644 (file)
@@ -165,6 +165,8 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
        u32 value2;
 
        if (emu->card_capabilities->emu_model) {
+               snd_emu1010_fpga_lock(emu);
+
                // This represents the S/PDIF lock status on 0404b, which is
                // kinda weird and unhelpful, because monitoring it via IRQ is
                // impractical (one gets an IRQ flood as long as it is desynced).
@@ -197,6 +199,8 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
                        snd_iprintf(buffer, "\nS/PDIF mode: %s%s\n",
                                    value & EMU_HANA_SPDIF_MODE_RX_PRO ? "professional" : "consumer",
                                    value & EMU_HANA_SPDIF_MODE_RX_NOCOPY ? ", no copy" : "");
+
+               snd_emu1010_fpga_unlock(emu);
        } else {
                snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS);
                snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS);
@@ -458,6 +462,9 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
        struct snd_emu10k1 *emu = entry->private_data;
        u32 value;
        int i;
+
+       snd_emu1010_fpga_lock(emu);
+
        snd_iprintf(buffer, "EMU1010 Registers:\n\n");
 
        for(i = 0; i < 0x40; i+=1) {
@@ -496,6 +503,8 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
                        snd_emu_proc_emu1010_link_read(emu, buffer, 0x701);
                }
        }
+
+       snd_emu1010_fpga_unlock(emu);
 }
 
 static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry,
index 74df2330015f66ef3930d05884092d74e4b100af..f4a1c2d4b0787518634dac52ebae9c41a01f05dc 100644 (file)
@@ -285,24 +285,33 @@ static void snd_emu1010_fpga_write_locked(struct snd_emu10k1 *emu, u32 reg, u32
        outw(value, emu->port + A_GPIO);
        udelay(10);
        outw(value | 0x80 , emu->port + A_GPIO);  /* High bit clocks the value into the fpga. */
+       udelay(10);
 }
 
 void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value)
 {
-       unsigned long flags;
+       if (snd_BUG_ON(!mutex_is_locked(&emu->emu1010.lock)))
+               return;
+       snd_emu1010_fpga_write_locked(emu, reg, value);
+}
 
-       spin_lock_irqsave(&emu->emu_lock, flags);
+void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value)
+{
+       snd_emu1010_fpga_lock(emu);
        snd_emu1010_fpga_write_locked(emu, reg, value);
-       spin_unlock_irqrestore(&emu->emu_lock, flags);
+       snd_emu1010_fpga_unlock(emu);
 }
 
-static void snd_emu1010_fpga_read_locked(struct snd_emu10k1 *emu, u32 reg, u32 *value)
+void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value)
 {
        // The higest input pin is used as the designated interrupt trigger,
        // so it needs to be masked out.
        // But note that any other input pin change will also cause an IRQ,
        // so using this function often causes an IRQ as a side effect.
        u32 mask = emu->card_capabilities->ca0108_chip ? 0x1f : 0x7f;
+
+       if (snd_BUG_ON(!mutex_is_locked(&emu->emu1010.lock)))
+               return;
        if (snd_BUG_ON(reg > 0x3f))
                return;
        reg += 0x40; /* 0x40 upwards are registers. */
@@ -313,47 +322,31 @@ static void snd_emu1010_fpga_read_locked(struct snd_emu10k1 *emu, u32 reg, u32 *
        *value = ((inw(emu->port + A_GPIO) >> 8) & mask);
 }
 
-void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&emu->emu_lock, flags);
-       snd_emu1010_fpga_read_locked(emu, reg, value);
-       spin_unlock_irqrestore(&emu->emu_lock, flags);
-}
-
 /* Each Destination has one and only one Source,
  * but one Source can feed any number of Destinations simultaneously.
  */
 void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src)
 {
-       unsigned long flags;
-
        if (snd_BUG_ON(dst & ~0x71f))
                return;
        if (snd_BUG_ON(src & ~0x71f))
                return;
-       spin_lock_irqsave(&emu->emu_lock, flags);
-       snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTHI, dst >> 8);
-       snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTLO, dst & 0x1f);
-       snd_emu1010_fpga_write_locked(emu, EMU_HANA_SRCHI, src >> 8);
-       snd_emu1010_fpga_write_locked(emu, EMU_HANA_SRCLO, src & 0x1f);
-       spin_unlock_irqrestore(&emu->emu_lock, flags);
+       snd_emu1010_fpga_write(emu, EMU_HANA_DESTHI, dst >> 8);
+       snd_emu1010_fpga_write(emu, EMU_HANA_DESTLO, dst & 0x1f);
+       snd_emu1010_fpga_write(emu, EMU_HANA_SRCHI, src >> 8);
+       snd_emu1010_fpga_write(emu, EMU_HANA_SRCLO, src & 0x1f);
 }
 
 u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst)
 {
-       unsigned long flags;
        u32 hi, lo;
 
        if (snd_BUG_ON(dst & ~0x71f))
                return 0;
-       spin_lock_irqsave(&emu->emu_lock, flags);
-       snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTHI, dst >> 8);
-       snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTLO, dst & 0x1f);
-       snd_emu1010_fpga_read_locked(emu, EMU_HANA_SRCHI, &hi);
-       snd_emu1010_fpga_read_locked(emu, EMU_HANA_SRCLO, &lo);
-       spin_unlock_irqrestore(&emu->emu_lock, flags);
+       snd_emu1010_fpga_write(emu, EMU_HANA_DESTHI, dst >> 8);
+       snd_emu1010_fpga_write(emu, EMU_HANA_DESTLO, dst & 0x1f);
+       snd_emu1010_fpga_read(emu, EMU_HANA_SRCHI, &hi);
+       snd_emu1010_fpga_read(emu, EMU_HANA_SRCLO, &lo);
        return (hi << 8) | lo;
 }
 
index 1a3f84599cb584331f9766ca6bd5b00bacaa580d..558c1f38fe971859d809e25d774069e73cc642b1 100644 (file)
@@ -644,6 +644,8 @@ static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56)
                ret = cs35l56_wait_for_firmware_boot(&cs35l56->base);
                if (ret)
                        goto err_powered_up;
+
+               regcache_cache_only(cs35l56->base.regmap, false);
        }
 
        /* Disable auto-hibernate so that runtime_pm has control */
@@ -1002,6 +1004,8 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id)
        if (ret)
                goto err;
 
+       regcache_cache_only(cs35l56->base.regmap, false);
+
        ret = cs35l56_set_patch(&cs35l56->base);
        if (ret)
                goto err;
index cdcb28aa9d7bf028d429aeea0016cec7c6bc0c22..b29739bd330b1331848553d1f2854694a1be369a 100644 (file)
@@ -920,6 +920,8 @@ static void alc_pre_init(struct hda_codec *codec)
        ((codec)->core.dev.power.power_state.event == PM_EVENT_RESUME)
 #define is_s4_resume(codec) \
        ((codec)->core.dev.power.power_state.event == PM_EVENT_RESTORE)
+#define is_s4_suspend(codec) \
+       ((codec)->core.dev.power.power_state.event == PM_EVENT_FREEZE)
 
 static int alc_init(struct hda_codec *codec)
 {
@@ -7183,6 +7185,46 @@ static void alc245_fixup_hp_spectre_x360_eu0xxx(struct hda_codec *codec,
        alc245_fixup_hp_gpio_led(codec, fix, action);
 }
 
+/*
+ * ALC287 PCM hooks
+ */
+static void alc287_alc1318_playback_pcm_hook(struct hda_pcm_stream *hinfo,
+                                  struct hda_codec *codec,
+                                  struct snd_pcm_substream *substream,
+                                  int action)
+{
+       alc_write_coef_idx(codec, 0x10, 0x8806); /* Change MLK to GPIO3 */
+       switch (action) {
+       case HDA_GEN_PCM_ACT_OPEN:
+               alc_write_coefex_idx(codec, 0x5a, 0x00, 0x954f); /* write gpio3 to high */
+               break;
+       case HDA_GEN_PCM_ACT_CLOSE:
+               alc_write_coefex_idx(codec, 0x5a, 0x00, 0x554f); /* write gpio3 as default value */
+               break;
+       }
+}
+
+static void __maybe_unused alc287_s4_power_gpio3_default(struct hda_codec *codec)
+{
+       if (is_s4_suspend(codec)) {
+               alc_write_coef_idx(codec, 0x10, 0x8806); /* Change MLK to GPIO3 */
+               alc_write_coefex_idx(codec, 0x5a, 0x00, 0x554f); /* write gpio3 as default value */
+       }
+}
+
+static void alc287_fixup_lenovo_thinkpad_with_alc1318(struct hda_codec *codec,
+                              const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+
+       if (action != HDA_FIXUP_ACT_PRE_PROBE)
+               return;
+#ifdef CONFIG_PM
+       spec->power_hook = alc287_s4_power_gpio3_default;
+#endif
+       spec->gen.pcm_playback_hook = alc287_alc1318_playback_pcm_hook;
+}
+
 
 enum {
        ALC269_FIXUP_GPIO2,
@@ -7426,6 +7468,7 @@ enum {
        ALC287_FIXUP_YOGA7_14ITL_SPEAKERS,
        ALC298_FIXUP_LENOVO_C940_DUET7,
        ALC287_FIXUP_LENOVO_14IRP8_DUETITL,
+       ALC287_FIXUP_LENOVO_LEGION_7,
        ALC287_FIXUP_13S_GEN2_SPEAKERS,
        ALC256_FIXUP_SET_COEF_DEFAULTS,
        ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
@@ -7467,6 +7510,11 @@ enum {
        ALC285_FIXUP_CS35L56_I2C_2,
        ALC285_FIXUP_CS35L56_I2C_4,
        ALC285_FIXUP_ASUS_GA403U,
+       ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC,
+       ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1,
+       ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC,
+       ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1,
+       ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318,
 };
 
 /* A special fixup for Lenovo C940 and Yoga Duet 7;
@@ -7506,6 +7554,23 @@ static void alc287_fixup_lenovo_14irp8_duetitl(struct hda_codec *codec,
        __snd_hda_apply_fixup(codec, id, action, 0);
 }
 
+/* Another hilarious PCI SSID conflict with Lenovo Legion Pro 7 16ARX8H (with
+ * TAS2781 codec) and Legion 7i 16IAX7 (with CS35L41 codec);
+ * we apply a corresponding fixup depending on the codec SSID instead
+ */
+static void alc287_fixup_lenovo_legion_7(struct hda_codec *codec,
+                                        const struct hda_fixup *fix,
+                                        int action)
+{
+       int id;
+
+       if (codec->core.subsystem_id == 0x17aa38a8)
+               id = ALC287_FIXUP_TAS2781_I2C; /* Legion Pro 7 16ARX8H */
+       else
+               id = ALC287_FIXUP_CS35L41_I2C_2; /* Legion 7i 16IAX7 */
+       __snd_hda_apply_fixup(codec, id, action, 0);
+}
+
 static const struct hda_fixup alc269_fixups[] = {
        [ALC269_FIXUP_GPIO2] = {
                .type = HDA_FIXUP_FUNC,
@@ -9400,6 +9465,10 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc287_fixup_lenovo_14irp8_duetitl,
        },
+       [ALC287_FIXUP_LENOVO_LEGION_7] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc287_fixup_lenovo_legion_7,
+       },
        [ALC287_FIXUP_13S_GEN2_SPEAKERS] = {
                .type = HDA_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -9690,6 +9759,44 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc285_fixup_asus_ga403u,
        },
+       [ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x03a11050 },
+                       { 0x1b, 0x03a11c30 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1
+       },
+       [ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc285_fixup_speaker2_to_dac1,
+               .chained = true,
+               .chain_id = ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC,
+       },
+       [ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x03a11050 },
+                       { 0x1b, 0x03a11c30 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC285_FIXUP_CS35L56_SPI_2
+       },
+       [ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc285_fixup_speaker2_to_dac1,
+               .chained = true,
+               .chain_id = ALC285_FIXUP_ASUS_GA403U,
+       },
+       [ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc287_fixup_lenovo_thinkpad_with_alc1318,
+               .chained = true,
+               .chain_id = ALC269_FIXUP_THINKPAD_ACPI
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -9901,6 +10008,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT),
        SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT),
        SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
+       SND_PCI_QUIRK(0x103c, 0x86c1, "HP Laptop 15-da3001TU", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
        SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO),
        SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
        SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
@@ -10084,6 +10192,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x8ca7, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8cdd, "HP Spectre", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x103c, 0x8cde, "HP Spectre", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x103c, 0x8cdf, "HP SnowWhite", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8ce0, "HP SnowWhite", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8cf5, "HP ZBook Studio 16", ALC245_FIXUP_CS35L41_SPI_4_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),
@@ -10143,7 +10253,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1a83, "ASUS UM5302LA", ALC294_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x1043, 0x1a8f, "ASUS UX582ZS", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1043, 0x1b11, "ASUS UX431DA", ALC294_FIXUP_ASUS_COEF_1B),
-       SND_PCI_QUIRK(0x1043, 0x1b13, "ASUS U41SV/GA403U", ALC285_FIXUP_ASUS_GA403U),
+       SND_PCI_QUIRK(0x1043, 0x1b13, "ASUS U41SV/GA403U", ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x1b93, "ASUS G614JVR/JIR", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1043, 0x1c03, "ASUS UM3406HA", ALC287_FIXUP_CS35L41_I2C_2),
@@ -10151,7 +10261,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1c33, "ASUS UX5304MA", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1043, 0x1c43, "ASUS UX8406MA", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
-       SND_PCI_QUIRK(0x1043, 0x1c63, "ASUS GU605M", ALC285_FIXUP_CS35L56_SPI_2),
+       SND_PCI_QUIRK(0x1043, 0x1c63, "ASUS GU605M", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1),
        SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS),
        SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JU/JV/JI", ALC285_FIXUP_ASUS_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JY/JZ/JI/JG", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
@@ -10228,6 +10338,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x152d, 0x1082, "Quanta NL3", ALC269_FIXUP_LIFEBOOK),
+       SND_PCI_QUIRK(0x152d, 0x1262, "Huawei NBLB-WAX9N", ALC2XX_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1558, 0x0353, "Clevo V35[05]SN[CDE]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x1323, "Clevo N130ZU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x1325, "Clevo N15[01][CW]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -10333,6 +10444,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x222e, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2231, "Thinkpad T560", ALC292_FIXUP_TPT460),
        SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC292_FIXUP_TPT460),
+       SND_PCI_QUIRK(0x17aa, 0x2234, "Thinkpad ICE-1", ALC287_FIXUP_TAS2781_I2C),
        SND_PCI_QUIRK(0x17aa, 0x2245, "Thinkpad T470", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2246, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2247, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
@@ -10353,6 +10465,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x2318, "Thinkpad Z13 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x2319, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
+       SND_PCI_QUIRK(0x17aa, 0x231e, "Thinkpad", ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318),
+       SND_PCI_QUIRK(0x17aa, 0x231f, "Thinkpad", ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318),
        SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
@@ -10382,7 +10496,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
        SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6),
        SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
-       SND_PCI_QUIRK(0x17aa, 0x386f, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x17aa, 0x386f, "Legion Pro 7/7i", ALC287_FIXUP_LENOVO_LEGION_7),
        SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C),
        SND_PCI_QUIRK(0x17aa, 0x3877, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x17aa, 0x3878, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
@@ -10394,8 +10508,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x3886, "Y780 VECO DUAL", ALC287_FIXUP_TAS2781_I2C),
        SND_PCI_QUIRK(0x17aa, 0x38a7, "Y780P AMD YG dual", ALC287_FIXUP_TAS2781_I2C),
        SND_PCI_QUIRK(0x17aa, 0x38a8, "Y780P AMD VECO dual", ALC287_FIXUP_TAS2781_I2C),
-       SND_PCI_QUIRK(0x17aa, 0x38a9, "Thinkbook 16P", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x38ab, "Thinkbook 16P", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x17aa, 0x38a9, "Thinkbook 16P", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
+       SND_PCI_QUIRK(0x17aa, 0x38ab, "Thinkbook 16P", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x38b4, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x17aa, 0x38b5, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x17aa, 0x38b6, "Legion Slim 7 16APH8", ALC287_FIXUP_CS35L41_I2C_2),
@@ -10457,6 +10571,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1d05, 0x115c, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
        SND_PCI_QUIRK(0x1d05, 0x121b, "TongFang GMxAGxx", ALC269_FIXUP_NO_SHUTUP),
        SND_PCI_QUIRK(0x1d05, 0x1387, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1d17, 0x3288, "Haier Boyue G42", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS),
        SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
        SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
index 48dae3339305048fca2262821e5ebfea6bcf237a..75f7674c66ee7ae8d9c407798193f4618b82a6b7 100644 (file)
@@ -514,10 +514,10 @@ static int tas2563_save_calibration(struct tasdevice_priv *tas_priv)
 static void tas2781_apply_calib(struct tasdevice_priv *tas_priv)
 {
        static const unsigned char page_array[CALIB_MAX] = {
-               0x17, 0x18, 0x18, 0x0d, 0x18
+               0x17, 0x18, 0x18, 0x13, 0x18,
        };
        static const unsigned char rgno_array[CALIB_MAX] = {
-               0x74, 0x0c, 0x14, 0x3c, 0x7c
+               0x74, 0x0c, 0x14, 0x70, 0x7c,
        };
        unsigned char *data;
        int i, j, rc;
index 69c68d8e7a6b54fc1fcfc3fac3a73d58403071f5..1760b5d42460afe83f3d50dbcdd73daf9455fc12 100644 (file)
@@ -430,6 +430,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "MRID6"),
                }
        },
+       {
+               .driver_data = &acp6x_card,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "MDC"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Herbag_MDU"),
+               }
+       },
        {
                .driver_data = &acp6x_card,
                .matches = {
index dfb4ce53491bbaa8800b8e7b3e2737a0a1be47bc..f8e57a2fc3e324fcf4cdefde12b3a8db24239af5 100644 (file)
@@ -1094,6 +1094,7 @@ static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_hw_cfg *hw_cf
 static int cs35l41_dsp_init(struct cs35l41_private *cs35l41)
 {
        struct wm_adsp *dsp;
+       uint32_t dsp1rx5_src;
        int ret;
 
        dsp = &cs35l41->dsp;
@@ -1113,16 +1114,29 @@ static int cs35l41_dsp_init(struct cs35l41_private *cs35l41)
                return ret;
        }
 
-       ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX5_SRC,
-                          CS35L41_INPUT_SRC_VPMON);
+       switch (cs35l41->hw_cfg.bst_type) {
+       case CS35L41_INT_BOOST:
+       case CS35L41_SHD_BOOST_ACTV:
+               dsp1rx5_src = CS35L41_INPUT_SRC_VPMON;
+               break;
+       case CS35L41_EXT_BOOST:
+       case CS35L41_SHD_BOOST_PASS:
+               dsp1rx5_src = CS35L41_INPUT_SRC_VBSTMON;
+               break;
+       default:
+               dev_err(cs35l41->dev, "wm_halo_init failed - Invalid Boost Type: %d\n",
+                       cs35l41->hw_cfg.bst_type);
+               goto err_dsp;
+       }
+
+       ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX5_SRC, dsp1rx5_src);
        if (ret < 0) {
-               dev_err(cs35l41->dev, "Write INPUT_SRC_VPMON failed: %d\n", ret);
+               dev_err(cs35l41->dev, "Write DSP1RX5_SRC: %d failed: %d\n", dsp1rx5_src, ret);
                goto err_dsp;
        }
-       ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX6_SRC,
-                          CS35L41_INPUT_SRC_CLASSH);
+       ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX6_SRC, CS35L41_INPUT_SRC_VBSTMON);
        if (ret < 0) {
-               dev_err(cs35l41->dev, "Write INPUT_SRC_CLASSH failed: %d\n", ret);
+               dev_err(cs35l41->dev, "Write CS35L41_INPUT_SRC_VBSTMON failed: %d\n", ret);
                goto err_dsp;
        }
        ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX7_SRC,
index 14a5f86019aad47390ee8f3962a596296dfbf437..70ff55c1517fe02d2a75e7d683e58edcb01947d0 100644 (file)
@@ -188,8 +188,6 @@ static void cs35l56_sdw_init(struct sdw_slave *peripheral)
                        goto out;
        }
 
-       regcache_cache_only(cs35l56->base.regmap, false);
-
        ret = cs35l56_init(cs35l56);
        if (ret < 0) {
                regcache_cache_only(cs35l56->base.regmap, true);
index 08cac58e3ab2223c82b4da10314f04b2f055b5b6..fd02b621da52c0c68420f995764e752b6a789597 100644 (file)
@@ -40,16 +40,11 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_set_patch, SND_SOC_CS35L56_SHARED);
 static const struct reg_default cs35l56_reg_defaults[] = {
        /* no defaults for OTP_MEM - first read populates cache */
 
-       { CS35L56_ASP1_ENABLES1,                0x00000000 },
-       { CS35L56_ASP1_CONTROL1,                0x00000028 },
-       { CS35L56_ASP1_CONTROL2,                0x18180200 },
-       { CS35L56_ASP1_CONTROL3,                0x00000002 },
-       { CS35L56_ASP1_FRAME_CONTROL1,          0x03020100 },
-       { CS35L56_ASP1_FRAME_CONTROL5,          0x00020100 },
-       { CS35L56_ASP1_DATA_CONTROL1,           0x00000018 },
-       { CS35L56_ASP1_DATA_CONTROL5,           0x00000018 },
-
-       /* no defaults for ASP1TX mixer */
+       /*
+        * No defaults for ASP1 control or ASP1TX mixer. See
+        * cs35l56_populate_asp1_register_defaults() and
+        * cs35l56_sync_asp1_mixer_widgets_with_firmware().
+        */
 
        { CS35L56_SWIRE_DP3_CH1_INPUT,          0x00000018 },
        { CS35L56_SWIRE_DP3_CH2_INPUT,          0x00000019 },
@@ -210,6 +205,36 @@ static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)
        }
 }
 
+static const struct reg_sequence cs35l56_asp1_defaults[] = {
+       REG_SEQ0(CS35L56_ASP1_ENABLES1,         0x00000000),
+       REG_SEQ0(CS35L56_ASP1_CONTROL1,         0x00000028),
+       REG_SEQ0(CS35L56_ASP1_CONTROL2,         0x18180200),
+       REG_SEQ0(CS35L56_ASP1_CONTROL3,         0x00000002),
+       REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL1,   0x03020100),
+       REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL5,   0x00020100),
+       REG_SEQ0(CS35L56_ASP1_DATA_CONTROL1,    0x00000018),
+       REG_SEQ0(CS35L56_ASP1_DATA_CONTROL5,    0x00000018),
+};
+
+/*
+ * The firmware can have control of the ASP so we don't provide regmap
+ * with defaults for these registers, to prevent a regcache_sync() from
+ * overwriting the firmware settings. But if the machine driver hooks up
+ * the ASP it means the driver is taking control of the ASP, so then the
+ * registers are populated with the defaults.
+ */
+int cs35l56_init_asp1_regs_for_driver_control(struct cs35l56_base *cs35l56_base)
+{
+       if (!cs35l56_base->fw_owns_asp1)
+               return 0;
+
+       cs35l56_base->fw_owns_asp1 = false;
+
+       return regmap_multi_reg_write(cs35l56_base->regmap, cs35l56_asp1_defaults,
+                                     ARRAY_SIZE(cs35l56_asp1_defaults));
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_init_asp1_regs_for_driver_control, SND_SOC_CS35L56_SHARED);
+
 /*
  * The firmware boot sequence can overwrite the ASP1 config registers so that
  * they don't match regmap's view of their values. Rewrite the values from the
@@ -217,19 +242,15 @@ static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)
  */
 int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base)
 {
-       struct reg_sequence asp1_regs[] = {
-               { .reg = CS35L56_ASP1_ENABLES1 },
-               { .reg = CS35L56_ASP1_CONTROL1 },
-               { .reg = CS35L56_ASP1_CONTROL2 },
-               { .reg = CS35L56_ASP1_CONTROL3 },
-               { .reg = CS35L56_ASP1_FRAME_CONTROL1 },
-               { .reg = CS35L56_ASP1_FRAME_CONTROL5 },
-               { .reg = CS35L56_ASP1_DATA_CONTROL1 },
-               { .reg = CS35L56_ASP1_DATA_CONTROL5 },
-       };
+       struct reg_sequence asp1_regs[ARRAY_SIZE(cs35l56_asp1_defaults)];
        int i, ret;
 
-       /* Read values from regmap cache into a write sequence */
+       if (cs35l56_base->fw_owns_asp1)
+               return 0;
+
+       memcpy(asp1_regs, cs35l56_asp1_defaults, sizeof(asp1_regs));
+
+       /* Read current values from regmap cache into the write sequence */
        for (i = 0; i < ARRAY_SIZE(asp1_regs); ++i) {
                ret = regmap_read(cs35l56_base->regmap, asp1_regs[i].reg, &asp1_regs[i].def);
                if (ret)
@@ -307,10 +328,10 @@ int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base)
                reg = CS35L56_DSP1_HALO_STATE;
 
        /*
-        * This can't be a regmap_read_poll_timeout() because cs35l56 will NAK
-        * I2C until it has booted which would terminate the poll
+        * The regmap must remain in cache-only until the chip has
+        * booted, so use a bypassed read of the status register.
         */
-       poll_ret = read_poll_timeout(regmap_read, read_ret,
+       poll_ret = read_poll_timeout(regmap_read_bypassed, read_ret,
                                     (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE),
                                     CS35L56_HALO_STATE_POLL_US,
                                     CS35L56_HALO_STATE_TIMEOUT_US,
@@ -362,7 +383,8 @@ void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire)
                return;
 
        cs35l56_wait_control_port_ready();
-       regcache_cache_only(cs35l56_base->regmap, false);
+
+       /* Leave in cache-only. This will be revoked when the chip has rebooted. */
 }
 EXPORT_SYMBOL_NS_GPL(cs35l56_system_reset, SND_SOC_CS35L56_SHARED);
 
@@ -577,14 +599,14 @@ int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_sou
                cs35l56_issue_wake_event(cs35l56_base);
 
 out_sync:
-       regcache_cache_only(cs35l56_base->regmap, false);
-
        ret = cs35l56_wait_for_firmware_boot(cs35l56_base);
        if (ret) {
                dev_err(cs35l56_base->dev, "Hibernate wake failed: %d\n", ret);
                goto err;
        }
 
+       regcache_cache_only(cs35l56_base->regmap, false);
+
        ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
        if (ret)
                goto err;
@@ -684,7 +706,7 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_calibration_controls, SND_SOC_CS35L56_SHARED);
 
 int cs35l56_get_calibration(struct cs35l56_base *cs35l56_base)
 {
-       u64 silicon_uid;
+       u64 silicon_uid = 0;
        int ret;
 
        /* Driver can't apply calibration to a secured part, so skip */
@@ -757,7 +779,7 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
         * devices so the REVID needs to be determined before waiting for the
         * firmware to boot.
         */
-       ret = regmap_read(cs35l56_base->regmap, CS35L56_REVID, &revid);
+       ret = regmap_read_bypassed(cs35l56_base->regmap, CS35L56_REVID, &revid);
        if (ret < 0) {
                dev_err(cs35l56_base->dev, "Get Revision ID failed\n");
                return ret;
@@ -768,7 +790,7 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
        if (ret)
                return ret;
 
-       ret = regmap_read(cs35l56_base->regmap, CS35L56_DEVID, &devid);
+       ret = regmap_read_bypassed(cs35l56_base->regmap, CS35L56_DEVID, &devid);
        if (ret < 0) {
                dev_err(cs35l56_base->dev, "Get Device ID failed\n");
                return ret;
@@ -787,6 +809,9 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
 
        cs35l56_base->type = devid & 0xFF;
 
+       /* Silicon is now identified and booted so exit cache-only */
+       regcache_cache_only(cs35l56_base->regmap, false);
+
        ret = regmap_read(cs35l56_base->regmap, CS35L56_DSP_RESTRICT_STS1, &secured);
        if (ret) {
                dev_err(cs35l56_base->dev, "Get Secure status failed\n");
index 8d2f021fb362812a73d07d10565a23d2b77f6a38..4986e78105daf9ca949815835c94321ad19dfb68 100644 (file)
@@ -454,9 +454,14 @@ static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int f
 {
        struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(codec_dai->component);
        unsigned int val;
+       int ret;
 
        dev_dbg(cs35l56->base.dev, "%s: %#x\n", __func__, fmt);
 
+       ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base);
+       if (ret)
+               return ret;
+
        switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
        case SND_SOC_DAIFMT_CBC_CFC:
                break;
@@ -530,6 +535,11 @@ static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx
                                        unsigned int rx_mask, int slots, int slot_width)
 {
        struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component);
+       int ret;
+
+       ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base);
+       if (ret)
+               return ret;
 
        if ((slots == 0) || (slot_width == 0)) {
                dev_dbg(cs35l56->base.dev, "tdm config cleared\n");
@@ -578,6 +588,11 @@ static int cs35l56_asp_dai_hw_params(struct snd_pcm_substream *substream,
        struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component);
        unsigned int rate = params_rate(params);
        u8 asp_width, asp_wl;
+       int ret;
+
+       ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base);
+       if (ret)
+               return ret;
 
        asp_wl = params_width(params);
        if (cs35l56->asp_slot_width)
@@ -634,7 +649,11 @@ static int cs35l56_asp_dai_set_sysclk(struct snd_soc_dai *dai,
                                      int clk_id, unsigned int freq, int dir)
 {
        struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component);
-       int freq_id;
+       int freq_id, ret;
+
+       ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base);
+       if (ret)
+               return ret;
 
        if (freq == 0) {
                cs35l56->sysclk_set = false;
@@ -1341,6 +1360,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
                                    "spk-id-gpios", ACPI_TYPE_PACKAGE, &obj);
        if (ret) {
                dev_dbg(cs35l56->base.dev, "Could not get spk-id-gpios package: %d\n", ret);
+               fwnode_handle_put(af01_fwnode);
                return -ENOENT;
        }
 
@@ -1348,6 +1368,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
        if (obj->package.count != 4) {
                dev_warn(cs35l56->base.dev, "Unexpected spk-id element count %d\n",
                         obj->package.count);
+               fwnode_handle_put(af01_fwnode);
                return -ENOENT;
        }
 
@@ -1362,6 +1383,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
                 */
                ret = acpi_dev_add_driver_gpios(adev, cs35l56_af01_spkid_gpios_mapping);
                if (ret) {
+                       fwnode_handle_put(af01_fwnode);
                        return dev_err_probe(cs35l56->base.dev, ret,
                                             "Failed to add gpio mapping to AF01\n");
                }
@@ -1369,14 +1391,17 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
                ret = devm_add_action_or_reset(cs35l56->base.dev,
                                               cs35l56_acpi_dev_release_driver_gpios,
                                               adev);
-               if (ret)
+               if (ret) {
+                       fwnode_handle_put(af01_fwnode);
                        return ret;
+               }
 
                dev_dbg(cs35l56->base.dev, "Added spk-id-gpios mapping to AF01\n");
        }
 
        desc = fwnode_gpiod_get_index(af01_fwnode, "spk-id", 0, GPIOD_IN, NULL);
        if (IS_ERR(desc)) {
+               fwnode_handle_put(af01_fwnode);
                ret = PTR_ERR(desc);
                return dev_err_probe(cs35l56->base.dev, ret, "Get GPIO from AF01 failed\n");
        }
@@ -1385,9 +1410,12 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
        gpiod_put(desc);
 
        if (ret < 0) {
+               fwnode_handle_put(af01_fwnode);
                dev_err_probe(cs35l56->base.dev, ret, "Error reading spk-id GPIO\n");
                return ret;
-               }
+       }
+
+       fwnode_handle_put(af01_fwnode);
 
        dev_info(cs35l56->base.dev, "Got spk-id from AF01\n");
 
@@ -1403,6 +1431,9 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
        cs35l56->base.cal_index = -1;
        cs35l56->speaker_id = -ENOENT;
 
+       /* Assume that the firmware owns ASP1 until we know different */
+       cs35l56->base.fw_owns_asp1 = true;
+
        dev_set_drvdata(cs35l56->base.dev, cs35l56);
 
        cs35l56_fill_supply_names(cs35l56->supplies);
@@ -1531,6 +1562,8 @@ post_soft_reset:
                        return ret;
 
                dev_dbg(cs35l56->base.dev, "Firmware rebooted after soft reset\n");
+
+               regcache_cache_only(cs35l56->base.regmap, false);
        }
 
        /* Disable auto-hibernate so that runtime_pm has control */
index 6bc068cdcbe2a89e1488530bfa4e6e9c49c0651c..15e5e3eb592b3008fb47ea4372fed71a08375f01 100644 (file)
@@ -671,8 +671,10 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev)
                return NULL;
 
        aad_pdata = devm_kzalloc(dev, sizeof(*aad_pdata), GFP_KERNEL);
-       if (!aad_pdata)
+       if (!aad_pdata) {
+               fwnode_handle_put(aad_np);
                return NULL;
+       }
 
        aad_pdata->irq = i2c->irq;
 
@@ -753,6 +755,8 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev)
        else
                aad_pdata->adc_1bit_rpt = DA7219_AAD_ADC_1BIT_RPT_1;
 
+       fwnode_handle_put(aad_np);
+
        return aad_pdata;
 }
 
index e3ba04484813a21904727a09725c608bf27c34a2..d0d24a53df7462cfe88d5d2457078fc1f144f22b 100644 (file)
@@ -444,6 +444,7 @@ struct rt5645_priv {
        struct regmap *regmap;
        struct i2c_client *i2c;
        struct gpio_desc *gpiod_hp_det;
+       struct gpio_desc *gpiod_cbj_sleeve;
        struct snd_soc_jack *hp_jack;
        struct snd_soc_jack *mic_jack;
        struct snd_soc_jack *btn_jack;
@@ -3186,6 +3187,9 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse
                regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2,
                        RT5645_CBJ_MN_JD, 0);
 
+               if (rt5645->gpiod_cbj_sleeve)
+                       gpiod_set_value(rt5645->gpiod_cbj_sleeve, 1);
+
                msleep(600);
                regmap_read(rt5645->regmap, RT5645_IN1_CTRL3, &val);
                val &= 0x7;
@@ -3202,6 +3206,8 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse
                        snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
                        snd_soc_dapm_sync(dapm);
                        rt5645->jack_type = SND_JACK_HEADPHONE;
+                       if (rt5645->gpiod_cbj_sleeve)
+                               gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
                }
                if (rt5645->pdata.level_trigger_irq)
                        regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
@@ -3229,6 +3235,9 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse
                if (rt5645->pdata.level_trigger_irq)
                        regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
                                RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
+
+               if (rt5645->gpiod_cbj_sleeve)
+                       gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
        }
 
        return rt5645->jack_type;
@@ -4012,6 +4021,16 @@ static int rt5645_i2c_probe(struct i2c_client *i2c)
                        return ret;
        }
 
+       rt5645->gpiod_cbj_sleeve = devm_gpiod_get_optional(&i2c->dev, "cbj-sleeve",
+                                                          GPIOD_OUT_LOW);
+
+       if (IS_ERR(rt5645->gpiod_cbj_sleeve)) {
+               ret = PTR_ERR(rt5645->gpiod_cbj_sleeve);
+               dev_info(&i2c->dev, "failed to initialize gpiod, ret=%d\n", ret);
+               if (ret != -ENOENT)
+                       return ret;
+       }
+
        for (i = 0; i < ARRAY_SIZE(rt5645->supplies); i++)
                rt5645->supplies[i].supply = rt5645_supply_names[i];
 
@@ -4259,6 +4278,9 @@ static void rt5645_i2c_remove(struct i2c_client *i2c)
        cancel_delayed_work_sync(&rt5645->jack_detect_work);
        cancel_delayed_work_sync(&rt5645->rcclock_work);
 
+       if (rt5645->gpiod_cbj_sleeve)
+               gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
+
        regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies);
 }
 
@@ -4274,6 +4296,9 @@ static void rt5645_i2c_shutdown(struct i2c_client *i2c)
                0);
        msleep(20);
        regmap_write(rt5645->regmap, RT5645_RESET, 0);
+
+       if (rt5645->gpiod_cbj_sleeve)
+               gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
 }
 
 static int __maybe_unused rt5645_sys_suspend(struct device *dev)
index 3fb7b9adb61de628705d784fbe64e259bf031089..bc3579203c7a4770cb657b22965a12bc2becefe8 100644 (file)
@@ -316,7 +316,7 @@ static int rt715_sdca_set_amp_gain_8ch_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -17625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0);
 static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
 
 static int rt715_sdca_get_volsw(struct snd_kcontrol *kcontrol,
@@ -477,7 +477,7 @@ static const struct snd_kcontrol_new rt715_sdca_snd_controls[] = {
                        RT715_SDCA_FU_VOL_CTRL, CH_01),
                SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL,
                        RT715_SDCA_FU_VOL_CTRL, CH_02),
-                       0x2f, 0x7f, 0,
+                       0x2f, 0x3f, 0,
                rt715_sdca_set_amp_gain_get, rt715_sdca_set_amp_gain_put,
                in_vol_tlv),
        RT715_SDCA_EXT_TLV("FU02 Capture Volume",
@@ -485,13 +485,13 @@ static const struct snd_kcontrol_new rt715_sdca_snd_controls[] = {
                        RT715_SDCA_FU_VOL_CTRL, CH_01),
                rt715_sdca_set_amp_gain_4ch_get,
                rt715_sdca_set_amp_gain_4ch_put,
-               in_vol_tlv, 4, 0x7f),
+               in_vol_tlv, 4, 0x3f),
        RT715_SDCA_EXT_TLV("FU06 Capture Volume",
                SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL,
                        RT715_SDCA_FU_VOL_CTRL, CH_01),
                rt715_sdca_set_amp_gain_4ch_get,
                rt715_sdca_set_amp_gain_4ch_put,
-               in_vol_tlv, 4, 0x7f),
+               in_vol_tlv, 4, 0x3f),
        /* MIC Boost Control */
        RT715_SDCA_BOOST_EXT_TLV("FU0E Boost",
                SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN,
index 7e13868ff99f03110c165dcd706cff46a8eeba5d..f012fe0ded6d2871217f5fa02c49ee0158ad5101 100644 (file)
@@ -111,6 +111,7 @@ static bool rt715_readable_register(struct device *dev, unsigned int reg)
        case 0x839d:
        case 0x83a7:
        case 0x83a9:
+       case 0x752001:
        case 0x752039:
                return true;
        default:
index e0ea3a23f7cc6844691338ff8daae7f2843d2c6e..e5bd9ef812de13378801d82356b54ee4144f219a 100644 (file)
@@ -1330,7 +1330,7 @@ static struct snd_soc_dai_driver rt722_sdca_dai[] = {
                .capture = {
                        .stream_name = "DP6 DMic Capture",
                        .channels_min = 1,
-                       .channels_max = 2,
+                       .channels_max = 4,
                        .rates = RT722_STEREO_RATES,
                        .formats = RT722_FORMATS,
                },
@@ -1439,9 +1439,12 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
        int loop_check, chk_cnt = 100, ret;
        unsigned int calib_status = 0;
 
-       /* Read eFuse */
-       rt722_sdca_index_write(rt722, RT722_VENDOR_SPK_EFUSE, RT722_DC_CALIB_CTRL,
-               0x4808);
+       /* Config analog bias */
+       rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_ANALOG_BIAS_CTL3,
+               0xa081);
+       /* GE related settings */
+       rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_GE_RELATED_CTL2,
+               0xa009);
        /* Button A, B, C, D bypass mode */
        rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_UMP_HID_CTL4,
                0xcf00);
@@ -1475,9 +1478,6 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
                if ((calib_status & 0x0040) == 0x0)
                        break;
        }
-       /* Release HP-JD, EN_CBJ_TIE_GL/R open, en_osw gating auto done bit */
-       rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_DIGITAL_MISC_CTRL4,
-               0x0010);
        /* Set ADC09 power entity floating control */
        rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ADC0A_08_PDE_FLOAT_CTL,
                0x2a12);
@@ -1490,8 +1490,21 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
        /* Set DAC03 and HP power entity floating control */
        rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_DAC03_HP_PDE_FLOAT_CTL,
                0x4040);
+       rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ENT_FLOAT_CTRL_1,
+               0x4141);
+       rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_FLOAT_CTRL_1,
+               0x0101);
        /* Fine tune PDE40 latency */
        regmap_write(rt722->regmap, 0x2f58, 0x07);
+       regmap_write(rt722->regmap, 0x2f03, 0x06);
+       /* MIC VRefo */
+       rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
+               RT722_COMBO_JACK_AUTO_CTL1, 0x0200, 0x0200);
+       rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
+               RT722_VREFO_GAT, 0x4000, 0x4000);
+       /* Release HP-JD, EN_CBJ_TIE_GL/R open, en_osw gating auto done bit */
+       rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_DIGITAL_MISC_CTRL4,
+               0x0010);
 }
 
 int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave)
index 44af8901352eb6817e9a6dddd76fc7325a3660ba..2464361a7958c6904d1eca01fb148166a4743eff 100644 (file)
@@ -69,6 +69,7 @@ struct rt722_sdca_dmic_kctrl_priv {
 #define RT722_COMBO_JACK_AUTO_CTL2             0x46
 #define RT722_COMBO_JACK_AUTO_CTL3             0x47
 #define RT722_DIGITAL_MISC_CTRL4               0x4a
+#define RT722_VREFO_GAT                                0x63
 #define RT722_FSM_CTL                          0x67
 #define RT722_SDCA_INTR_REC                    0x82
 #define RT722_SW_CONFIG1                       0x8a
@@ -127,6 +128,8 @@ struct rt722_sdca_dmic_kctrl_priv {
 #define RT722_UMP_HID_CTL6                     0x66
 #define RT722_UMP_HID_CTL7                     0x67
 #define RT722_UMP_HID_CTL8                     0x68
+#define RT722_FLOAT_CTRL_1                     0x70
+#define RT722_ENT_FLOAT_CTRL_1         0x76
 
 /* Parameter & Verb control 01 (0x1a)(NID:20h) */
 #define RT722_HIDDEN_REG_SW_RESET (0x1 << 14)
index 3c025dabaf7a47f180b6f5bdaf6d6f67d128956d..1253695bebd863cab4accfef0616250fb3006830 100644 (file)
@@ -1155,6 +1155,7 @@ static int wsa881x_probe(struct sdw_slave *pdev,
        pdev->prop.sink_ports = GENMASK(WSA881X_MAX_SWR_PORTS, 0);
        pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop;
        pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
+       pdev->prop.clk_stop_mode1 = true;
        gpiod_direction_output(wsa881x->sd_n, !wsa881x->sd_n_val);
 
        wsa881x->regmap = devm_regmap_init_sdw(pdev, &wsa881x_regmap_config);
index 9d9921e1cd4dedcb2ff4f8e9b59a3b4560d7fa4c..d2554c8577326b533764862829e84b8e001f7016 100644 (file)
@@ -64,7 +64,7 @@ struct avs_icl_memwnd2_desc {
 struct avs_icl_memwnd2 {
        union {
                struct avs_icl_memwnd2_desc slot_desc[AVS_ICL_MEMWND2_SLOTS_COUNT];
-               u8 rsvd[PAGE_SIZE];
+               u8 rsvd[SZ_4K];
        };
        u8 slot_array[AVS_ICL_MEMWND2_SLOTS_COUNT][PAGE_SIZE];
 } __packed;
index 13061bd1488bb4dd506b14aed5c87967bc19aee6..42b42903ae9de7919c6620a5bfba2ef3b54ffb2c 100644 (file)
@@ -1582,6 +1582,8 @@ static int avs_widget_load(struct snd_soc_component *comp, int index,
        if (!le32_to_cpu(dw->priv.size))
                return 0;
 
+       w->no_wname_in_kcontrol_name = true;
+
        if (w->ignore_suspend && !AVS_S0IX_SUPPORTED) {
                dev_info_once(comp->dev, "Device does not support S0IX, check BIOS settings\n");
                w->ignore_suspend = false;
index 05f38d1f7d824dc0f46c5262e0f6616dce1b7411..b41a1147f1c3455de581c729efc72517b35bc6c7 100644 (file)
@@ -636,28 +636,30 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
                                        BYT_RT5640_USE_AMCR0F28),
        },
        {
+               /* Asus T100TAF, unlike other T100TA* models this one has a mono speaker */
                .matches = {
                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),
                },
                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
                                        BYT_RT5640_JD_SRC_JD2_IN4N |
                                        BYT_RT5640_OVCD_TH_2000UA |
                                        BYT_RT5640_OVCD_SF_0P75 |
+                                       BYT_RT5640_MONO_SPEAKER |
+                                       BYT_RT5640_DIFF_MIC |
+                                       BYT_RT5640_SSP0_AIF2 |
                                        BYT_RT5640_MCLK_EN),
        },
        {
+               /* Asus T100TA and T100TAM, must come after T100TAF (mono spk) match */
                .matches = {
-                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "T100TA"),
                },
                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
                                        BYT_RT5640_JD_SRC_JD2_IN4N |
                                        BYT_RT5640_OVCD_TH_2000UA |
                                        BYT_RT5640_OVCD_SF_0P75 |
-                                       BYT_RT5640_MONO_SPEAKER |
-                                       BYT_RT5640_DIFF_MIC |
-                                       BYT_RT5640_SSP0_AIF2 |
                                        BYT_RT5640_MCLK_EN),
        },
        {
index b93ea33739f29ddd9b987d7896e9fa2f37c58ccf..6458d5dc4902f665211bb9e4ae7d274e4bff2fdc 100644 (file)
@@ -99,6 +99,7 @@ config SND_MESON_AXG_PDM
 
 config SND_MESON_CARD_UTILS
        tristate
+       select SND_DYNAMIC_MINORS
 
 config SND_MESON_CODEC_GLUE
        tristate
index 3180aa4d3a157e2718b7b3b4bf34a239a68f33e1..8c5605c1e34e8a1bf29e4256ba9625b94205c762 100644 (file)
@@ -318,6 +318,7 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np,
 
        dai_link->cpus = cpu;
        dai_link->num_cpus = 1;
+       dai_link->nonatomic = true;
 
        ret = meson_card_parse_dai(card, np, dai_link->cpus);
        if (ret)
index bebee0ca8e3889a920a486b01c1a8730eb1988d4..ecb3eb7a9723ddf60e565b95e46b7f31ce1544cb 100644 (file)
@@ -204,18 +204,26 @@ static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id)
        unsigned int status;
 
        regmap_read(fifo->map, FIFO_STATUS1, &status);
-
        status = FIELD_GET(STATUS1_INT_STS, status);
+       axg_fifo_ack_irq(fifo, status);
+
+       /* Use the thread to call period elapsed on nonatomic links */
        if (status & FIFO_INT_COUNT_REPEAT)
-               snd_pcm_period_elapsed(ss);
-       else
-               dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n",
-                       status);
+               return IRQ_WAKE_THREAD;
 
-       /* Ack irqs */
-       axg_fifo_ack_irq(fifo, status);
+       dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n",
+               status);
+
+       return IRQ_NONE;
+}
+
+static irqreturn_t axg_fifo_pcm_irq_block_thread(int irq, void *dev_id)
+{
+       struct snd_pcm_substream *ss = dev_id;
+
+       snd_pcm_period_elapsed(ss);
 
-       return IRQ_RETVAL(status);
+       return IRQ_HANDLED;
 }
 
 int axg_fifo_pcm_open(struct snd_soc_component *component,
@@ -243,8 +251,9 @@ int axg_fifo_pcm_open(struct snd_soc_component *component,
        if (ret)
                return ret;
 
-       ret = request_irq(fifo->irq, axg_fifo_pcm_irq_block, 0,
-                         dev_name(dev), ss);
+       ret = request_threaded_irq(fifo->irq, axg_fifo_pcm_irq_block,
+                                  axg_fifo_pcm_irq_block_thread,
+                                  IRQF_ONESHOT, dev_name(dev), ss);
        if (ret)
                return ret;
 
index 63333a2b0a9c363d6882d3fe50ecff78da390316..a6579efd37750db01add3c491bb7a8443a76dde7 100644 (file)
@@ -392,6 +392,46 @@ void axg_tdm_stream_free(struct axg_tdm_stream *ts)
 }
 EXPORT_SYMBOL_GPL(axg_tdm_stream_free);
 
+int axg_tdm_stream_set_cont_clocks(struct axg_tdm_stream *ts,
+                                  unsigned int fmt)
+{
+       int ret = 0;
+
+       if (fmt & SND_SOC_DAIFMT_CONT) {
+               /* Clock are already enabled - skipping */
+               if (ts->clk_enabled)
+                       return 0;
+
+               ret = clk_prepare_enable(ts->iface->mclk);
+               if (ret)
+                       return ret;
+
+               ret = clk_prepare_enable(ts->iface->sclk);
+               if (ret)
+                       goto err_sclk;
+
+               ret = clk_prepare_enable(ts->iface->lrclk);
+               if (ret)
+                       goto err_lrclk;
+
+               ts->clk_enabled = true;
+               return 0;
+       }
+
+       /* Clocks are already disabled - skipping */
+       if (!ts->clk_enabled)
+               return 0;
+
+       clk_disable_unprepare(ts->iface->lrclk);
+err_lrclk:
+       clk_disable_unprepare(ts->iface->sclk);
+err_sclk:
+       clk_disable_unprepare(ts->iface->mclk);
+       ts->clk_enabled = false;
+       return ret;
+}
+EXPORT_SYMBOL_GPL(axg_tdm_stream_set_cont_clocks);
+
 MODULE_DESCRIPTION("Amlogic AXG TDM formatter driver");
 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
 MODULE_LICENSE("GPL v2");
index bf708717635bf6531195a1039aee41c3166d8154..62057c71f742e68e4555428281157ebb265b1cc2 100644 (file)
@@ -309,6 +309,7 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream,
                                   struct snd_soc_dai *dai)
 {
        struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai);
+       struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
        int ret;
 
        switch (iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -346,7 +347,11 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream,
                        return ret;
        }
 
-       return 0;
+       ret = axg_tdm_stream_set_cont_clocks(ts, iface->fmt);
+       if (ret)
+               dev_err(dai->dev, "failed to apply continuous clock setting\n");
+
+       return ret;
 }
 
 static int axg_tdm_iface_hw_free(struct snd_pcm_substream *substream,
@@ -354,19 +359,32 @@ static int axg_tdm_iface_hw_free(struct snd_pcm_substream *substream,
 {
        struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
 
-       /* Stop all attached formatters */
-       axg_tdm_stream_stop(ts);
-
-       return 0;
+       return axg_tdm_stream_set_cont_clocks(ts, 0);
 }
 
-static int axg_tdm_iface_prepare(struct snd_pcm_substream *substream,
+static int axg_tdm_iface_trigger(struct snd_pcm_substream *substream,
+                                int cmd,
                                 struct snd_soc_dai *dai)
 {
-       struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
+       struct axg_tdm_stream *ts =
+               snd_soc_dai_get_dma_data(dai, substream);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               axg_tdm_stream_start(ts);
+               break;
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+       case SNDRV_PCM_TRIGGER_STOP:
+               axg_tdm_stream_stop(ts);
+               break;
+       default:
+               return -EINVAL;
+       }
 
-       /* Force all attached formatters to update */
-       return axg_tdm_stream_reset(ts);
+       return 0;
 }
 
 static int axg_tdm_iface_remove_dai(struct snd_soc_dai *dai)
@@ -412,8 +430,8 @@ static const struct snd_soc_dai_ops axg_tdm_iface_ops = {
        .set_fmt        = axg_tdm_iface_set_fmt,
        .startup        = axg_tdm_iface_startup,
        .hw_params      = axg_tdm_iface_hw_params,
-       .prepare        = axg_tdm_iface_prepare,
        .hw_free        = axg_tdm_iface_hw_free,
+       .trigger        = axg_tdm_iface_trigger,
 };
 
 /* TDM Backend DAIs */
index 42f7470b9a7f41fd948948c54d58ea30c49831be..daaca10fec9e2bff82164ccccea75f1aefadaba1 100644 (file)
@@ -58,12 +58,17 @@ struct axg_tdm_stream {
        unsigned int physical_width;
        u32 *mask;
        bool ready;
+
+       /* For continuous clock tracking */
+       bool clk_enabled;
 };
 
 struct axg_tdm_stream *axg_tdm_stream_alloc(struct axg_tdm_iface *iface);
 void axg_tdm_stream_free(struct axg_tdm_stream *ts);
 int axg_tdm_stream_start(struct axg_tdm_stream *ts);
 void axg_tdm_stream_stop(struct axg_tdm_stream *ts);
+int axg_tdm_stream_set_cont_clocks(struct axg_tdm_stream *ts,
+                                  unsigned int fmt);
 
 static inline int axg_tdm_stream_reset(struct axg_tdm_stream *ts)
 {
index cc84d4c81be9d363d701b1d5c658e26a62079435..238bda5f6b76fa48b186514398840af05644f279 100644 (file)
@@ -350,7 +350,9 @@ static int sof_init_environment(struct snd_sof_dev *sdev)
        }
 
        ret = sof_select_ipc_and_paths(sdev);
-       if (!ret && plat_data->ipc_type != base_profile->ipc_type) {
+       if (ret) {
+               goto err_machine_check;
+       } else if (plat_data->ipc_type != base_profile->ipc_type) {
                /* IPC type changed, re-initialize the ops */
                sof_ops_free(sdev);
 
index 7c8aafca8fdef8eb65211dcd8cbead13077a6068..7275437ea8d8a59433e4aab0429acb4ce66cdf4a 100644 (file)
@@ -330,14 +330,32 @@ EXPORT_SYMBOL_GPL(snd_sof_dbg_memory_info_init);
 
 int snd_sof_dbg_init(struct snd_sof_dev *sdev)
 {
+       struct snd_sof_pdata *plat_data = sdev->pdata;
        struct snd_sof_dsp_ops *ops = sof_ops(sdev);
        const struct snd_sof_debugfs_map *map;
+       struct dentry *fw_profile;
        int i;
        int err;
 
        /* use "sof" as top level debugFS dir */
        sdev->debugfs_root = debugfs_create_dir("sof", NULL);
 
+       /* expose firmware/topology prefix/names for test purposes */
+       fw_profile = debugfs_create_dir("fw_profile", sdev->debugfs_root);
+
+       debugfs_create_str("fw_path", 0444, fw_profile,
+                          (char **)&plat_data->fw_filename_prefix);
+       debugfs_create_str("fw_lib_path", 0444, fw_profile,
+                          (char **)&plat_data->fw_lib_prefix);
+       debugfs_create_str("tplg_path", 0444, fw_profile,
+                          (char **)&plat_data->tplg_filename_prefix);
+       debugfs_create_str("fw_name", 0444, fw_profile,
+                          (char **)&plat_data->fw_filename);
+       debugfs_create_str("tplg_name", 0444, fw_profile,
+                          (char **)&plat_data->tplg_filename);
+       debugfs_create_u32("ipc_type", 0444, fw_profile,
+                          (u32 *)&plat_data->ipc_type);
+
        /* init dfsentry list */
        INIT_LIST_HEAD(&sdev->dfsentry_list);
 
index b26ffe767fab553467897b4facc13931668b27fe..b14e508f1f315b19585ad6851f8fc5f4b1d3891a 100644 (file)
@@ -35,6 +35,9 @@ static const struct sof_dev_desc lnl_desc = {
        .default_fw_path = {
                [SOF_IPC_TYPE_4] = "intel/sof-ipc4/lnl",
        },
+       .default_lib_path = {
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/lnl",
+       },
        .default_tplg_path = {
                [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
        },
index 35769dd7905ebe6f66492f650a72d8624712f28a..af0bf354cb209e216b60ec0097ac88fb08b21475 100644 (file)
@@ -434,4 +434,5 @@ const struct sof_ipc_pcm_ops ipc3_pcm_ops = {
        .trigger = sof_ipc3_pcm_trigger,
        .dai_link_fixup = sof_ipc3_pcm_dai_link_fixup,
        .reset_hw_params_during_stop = true,
+       .d0i3_supported_in_s0ix = true,
 };
index e915f9f87a6c35d74f1cf7096accca70dce688da..4594470ed08b1e6e95af6e2aaa62da418281ce97 100644 (file)
@@ -37,6 +37,25 @@ struct sof_ipc4_timestamp_info {
        snd_pcm_sframes_t delay;
 };
 
+/**
+ * struct sof_ipc4_pcm_stream_priv - IPC4 specific private data
+ * @time_info: pointer to time info struct if it is supported, otherwise NULL
+ * @chain_dma_allocated: indicates the ChainDMA allocation state
+ */
+struct sof_ipc4_pcm_stream_priv {
+       struct sof_ipc4_timestamp_info *time_info;
+
+       bool chain_dma_allocated;
+};
+
+static inline struct sof_ipc4_timestamp_info *
+sof_ipc4_sps_to_time_info(struct snd_sof_pcm_stream *sps)
+{
+       struct sof_ipc4_pcm_stream_priv *stream_priv = sps->private;
+
+       return stream_priv->time_info;
+}
+
 static int sof_ipc4_set_multi_pipeline_state(struct snd_sof_dev *sdev, u32 state,
                                             struct ipc4_pipeline_set_state_data *trigger_list)
 {
@@ -253,14 +272,17 @@ sof_ipc4_update_pipeline_state(struct snd_sof_dev *sdev, int state, int cmd,
  */
 
 static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev,
-                                     int direction,
+                                     struct snd_sof_pcm *spcm, int direction,
                                      struct snd_sof_pcm_stream_pipeline_list *pipeline_list,
                                      int state, int cmd)
 {
        struct sof_ipc4_fw_data *ipc4_data = sdev->private;
+       struct sof_ipc4_pcm_stream_priv *stream_priv;
        bool allocate, enable, set_fifo_size;
        struct sof_ipc4_msg msg = {{ 0 }};
-       int i;
+       int ret, i;
+
+       stream_priv = spcm->stream[direction].private;
 
        switch (state) {
        case SOF_IPC4_PIPE_RUNNING: /* Allocate and start chained dma */
@@ -281,6 +303,11 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev,
                set_fifo_size = false;
                break;
        case SOF_IPC4_PIPE_RESET: /* Disable and free chained DMA. */
+
+               /* ChainDMA can only be reset if it has been allocated */
+               if (!stream_priv->chain_dma_allocated)
+                       return 0;
+
                allocate = false;
                enable = false;
                set_fifo_size = false;
@@ -338,7 +365,12 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev,
        if (enable)
                msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_ENABLE_MASK;
 
-       return sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0);
+       ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0);
+       /* Update the ChainDMA allocation state */
+       if (!ret)
+               stream_priv->chain_dma_allocated = allocate;
+
+       return ret;
 }
 
 static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
@@ -378,7 +410,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
         * trigger function that handles the rest for the substream.
         */
        if (pipeline->use_chain_dma)
-               return sof_ipc4_chain_dma_trigger(sdev, substream->stream,
+               return sof_ipc4_chain_dma_trigger(sdev, spcm, substream->stream,
                                                  pipeline_list, state, cmd);
 
        /* allocate memory for the pipeline data */
@@ -452,7 +484,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
                 * Invalidate the stream_start_offset to make sure that it is
                 * going to be updated if the stream resumes
                 */
-               time_info = spcm->stream[substream->stream].private;
+               time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]);
                if (time_info)
                        time_info->stream_start_offset = SOF_IPC4_INVALID_STREAM_POSITION;
 
@@ -706,12 +738,16 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
 static void sof_ipc4_pcm_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm)
 {
        struct snd_sof_pcm_stream_pipeline_list *pipeline_list;
+       struct sof_ipc4_pcm_stream_priv *stream_priv;
        int stream;
 
        for_each_pcm_streams(stream) {
                pipeline_list = &spcm->stream[stream].pipeline_list;
                kfree(pipeline_list->pipelines);
                pipeline_list->pipelines = NULL;
+
+               stream_priv = spcm->stream[stream].private;
+               kfree(stream_priv->time_info);
                kfree(spcm->stream[stream].private);
                spcm->stream[stream].private = NULL;
        }
@@ -721,7 +757,8 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
 {
        struct snd_sof_pcm_stream_pipeline_list *pipeline_list;
        struct sof_ipc4_fw_data *ipc4_data = sdev->private;
-       struct sof_ipc4_timestamp_info *stream_info;
+       struct sof_ipc4_pcm_stream_priv *stream_priv;
+       struct sof_ipc4_timestamp_info *time_info;
        bool support_info = true;
        u32 abi_version;
        u32 abi_offset;
@@ -749,33 +786,41 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
                        return -ENOMEM;
                }
 
+               stream_priv = kzalloc(sizeof(*stream_priv), GFP_KERNEL);
+               if (!stream_priv) {
+                       sof_ipc4_pcm_free(sdev, spcm);
+                       return -ENOMEM;
+               }
+
+               spcm->stream[stream].private = stream_priv;
+
                if (!support_info)
                        continue;
 
-               stream_info = kzalloc(sizeof(*stream_info), GFP_KERNEL);
-               if (!stream_info) {
+               time_info = kzalloc(sizeof(*time_info), GFP_KERNEL);
+               if (!time_info) {
                        sof_ipc4_pcm_free(sdev, spcm);
                        return -ENOMEM;
                }
 
-               spcm->stream[stream].private = stream_info;
+               stream_priv->time_info = time_info;
        }
 
        return 0;
 }
 
-static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *spcm)
+static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sps)
 {
        struct sof_ipc4_copier *host_copier = NULL;
        struct sof_ipc4_copier *dai_copier = NULL;
        struct sof_ipc4_llp_reading_slot llp_slot;
-       struct sof_ipc4_timestamp_info *info;
+       struct sof_ipc4_timestamp_info *time_info;
        struct snd_soc_dapm_widget *widget;
        struct snd_sof_dai *dai;
        int i;
 
        /* find host & dai to locate info in memory window */
-       for_each_dapm_widgets(spcm->list, i, widget) {
+       for_each_dapm_widgets(sps->list, i, widget) {
                struct snd_sof_widget *swidget = widget->dobj.private;
 
                if (!swidget)
@@ -795,44 +840,44 @@ static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pc
                return;
        }
 
-       info = spcm->private;
-       info->host_copier = host_copier;
-       info->dai_copier = dai_copier;
-       info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_gpdma_reading_slots) +
-                                   sdev->fw_info_box.offset;
+       time_info = sof_ipc4_sps_to_time_info(sps);
+       time_info->host_copier = host_copier;
+       time_info->dai_copier = dai_copier;
+       time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers,
+                                        llp_gpdma_reading_slots) + sdev->fw_info_box.offset;
 
        /* find llp slot used by current dai */
        for (i = 0; i < SOF_IPC4_MAX_LLP_GPDMA_READING_SLOTS; i++) {
-               sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot));
+               sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot));
                if (llp_slot.node_id == dai_copier->data.gtw_cfg.node_id)
                        break;
 
-               info->llp_offset += sizeof(llp_slot);
+               time_info->llp_offset += sizeof(llp_slot);
        }
 
        if (i < SOF_IPC4_MAX_LLP_GPDMA_READING_SLOTS)
                return;
 
        /* if no llp gpdma slot is used, check aggregated sdw slot */
-       info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_sndw_reading_slots) +
-                                       sdev->fw_info_box.offset;
+       time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers,
+                                        llp_sndw_reading_slots) + sdev->fw_info_box.offset;
        for (i = 0; i < SOF_IPC4_MAX_LLP_SNDW_READING_SLOTS; i++) {
-               sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot));
+               sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot));
                if (llp_slot.node_id == dai_copier->data.gtw_cfg.node_id)
                        break;
 
-               info->llp_offset += sizeof(llp_slot);
+               time_info->llp_offset += sizeof(llp_slot);
        }
 
        if (i < SOF_IPC4_MAX_LLP_SNDW_READING_SLOTS)
                return;
 
        /* check EVAD slot */
-       info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_evad_reading_slot) +
-                                       sdev->fw_info_box.offset;
-       sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot));
+       time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers,
+                                        llp_evad_reading_slot) + sdev->fw_info_box.offset;
+       sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot));
        if (llp_slot.node_id != dai_copier->data.gtw_cfg.node_id)
-               info->llp_offset = 0;
+               time_info->llp_offset = 0;
 }
 
 static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
@@ -849,7 +894,7 @@ static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
        if (!spcm)
                return -EINVAL;
 
-       time_info = spcm->stream[substream->stream].private;
+       time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]);
        /* delay calculation is not supported by current fw_reg ABI */
        if (!time_info)
                return 0;
@@ -864,7 +909,7 @@ static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
 
 static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev,
                                            struct snd_pcm_substream *substream,
-                                           struct snd_sof_pcm_stream *stream,
+                                           struct snd_sof_pcm_stream *sps,
                                            struct sof_ipc4_timestamp_info *time_info)
 {
        struct sof_ipc4_copier *host_copier = time_info->host_copier;
@@ -918,7 +963,7 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
        struct sof_ipc4_timestamp_info *time_info;
        struct sof_ipc4_llp_reading_slot llp;
        snd_pcm_uframes_t head_cnt, tail_cnt;
-       struct snd_sof_pcm_stream *stream;
+       struct snd_sof_pcm_stream *sps;
        u64 dai_cnt, host_cnt, host_ptr;
        struct snd_sof_pcm *spcm;
        int ret;
@@ -927,8 +972,8 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
        if (!spcm)
                return -EOPNOTSUPP;
 
-       stream = &spcm->stream[substream->stream];
-       time_info = stream->private;
+       sps = &spcm->stream[substream->stream];
+       time_info = sof_ipc4_sps_to_time_info(sps);
        if (!time_info)
                return -EOPNOTSUPP;
 
@@ -938,7 +983,7 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
         * the statistics is complete. And it will not change after the first initiailization.
         */
        if (time_info->stream_start_offset == SOF_IPC4_INVALID_STREAM_POSITION) {
-               ret = sof_ipc4_get_stream_start_offset(sdev, substream, stream, time_info);
+               ret = sof_ipc4_get_stream_start_offset(sdev, substream, sps, time_info);
                if (ret < 0)
                        return -EOPNOTSUPP;
        }
@@ -1030,15 +1075,13 @@ static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component,
 {
        struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
        struct sof_ipc4_timestamp_info *time_info;
-       struct snd_sof_pcm_stream *stream;
        struct snd_sof_pcm *spcm;
 
        spcm = snd_sof_find_spcm_dai(component, rtd);
        if (!spcm)
                return 0;
 
-       stream = &spcm->stream[substream->stream];
-       time_info = stream->private;
+       time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]);
        /*
         * Report the stored delay value calculated in the pointer callback.
         * In the unlikely event that the calculation was skipped/aborted, the
index f03cee94bce62642e3c419d4f956a2011ea4dd3f..8804e00e7251b9724054b119509698a3a12899bf 100644 (file)
@@ -325,14 +325,13 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
                        ipc_first = true;
                break;
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               if (sdev->system_suspend_target == SOF_SUSPEND_S0IX &&
+               /*
+                * If DSP D0I3 is allowed during S0iX, set the suspend_ignored flag for
+                * D0I3-compatible streams to keep the firmware pipeline running
+                */
+               if (pcm_ops && pcm_ops->d0i3_supported_in_s0ix &&
+                   sdev->system_suspend_target == SOF_SUSPEND_S0IX &&
                    spcm->stream[substream->stream].d0i3_compatible) {
-                       /*
-                        * trap the event, not sending trigger stop to
-                        * prevent the FW pipelines from being stopped,
-                        * and mark the flag to ignore the upcoming DAPM
-                        * PM events.
-                        */
                        spcm->stream[substream->stream].suspend_ignored = true;
                        return 0;
                }
index 86bbb531e142c72be1ca5d710c466d16c9058734..499b6084b52637f12623172b0b17d027a41c08d4 100644 (file)
@@ -116,6 +116,7 @@ struct snd_sof_dai_config_data {
  *                               triggers. The FW keeps the host DMA running in this case and
  *                               therefore the host must do the same and should stop the DMA during
  *                               hw_free.
+ * @d0i3_supported_in_s0ix: Allow DSP D0I3 during S0iX
  */
 struct sof_ipc_pcm_ops {
        int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream,
@@ -135,6 +136,7 @@ struct sof_ipc_pcm_ops {
        bool reset_hw_params_during_stop;
        bool ipc_first_on_start;
        bool platform_stop_during_hw_free;
+       bool d0i3_supported_in_s0ix;
 };
 
 /**
index aa37c4ab0adbd9b47d2228cb4977e78ebf97b576..21cd41fec7a9cb932ecdc479ca41394349c48ffc 100644 (file)
@@ -1,8 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 //
 // tegra186_dspk.c - Tegra186 DSPK driver
-//
-// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
 
 #include <linux/clk.h>
 #include <linux/device.h>
@@ -241,14 +240,14 @@ static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       cif_conf.client_bits = TEGRA_ACIF_BITS_24;
-
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
                cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
+               cif_conf.client_bits = TEGRA_ACIF_BITS_16;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
                cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
+               cif_conf.client_bits = TEGRA_ACIF_BITS_24;
                break;
        default:
                dev_err(dev, "unsupported format!\n");
index b892d66f78470a6430b7096efdafab202992dbd2..1e760c3155213db093ff09a12b922eb43c3ba4c4 100644 (file)
@@ -2417,12 +2417,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 
        mcasp_reparent_fck(pdev);
 
-       ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
-                                             &davinci_mcasp_dai[mcasp->op_mode], 1);
-
-       if (ret != 0)
-               goto err;
-
        ret = davinci_mcasp_get_dma_type(mcasp);
        switch (ret) {
        case PCM_EDMA:
@@ -2449,6 +2443,12 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
                goto err;
        }
 
+       ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
+                                             &davinci_mcasp_dai[mcasp->op_mode], 1);
+
+       if (ret != 0)
+               goto err;
+
 no_audio:
        ret = davinci_mcasp_init_gpiochip(mcasp);
        if (ret) {
index 7c7493cb571f97bf98b0b4841aeb756d43990718..52f076afeb96006c42dfee6edefcf348048af96b 100644 (file)
@@ -61,6 +61,7 @@
 #define ARM_CPU_IMP_HISI               0x48
 #define ARM_CPU_IMP_APPLE              0x61
 #define ARM_CPU_IMP_AMPERE             0xC0
+#define ARM_CPU_IMP_MICROSOFT          0x6D
 
 #define ARM_CPU_PART_AEM_V8            0xD0F
 #define ARM_CPU_PART_FOUNDATION                0xD00
 
 #define AMPERE_CPU_PART_AMPERE1                0xAC3
 
+#define MICROSOFT_CPU_PART_AZURE_COBALT_100    0xD49 /* Based on r0p0 of ARM Neoverse N2 */
+
 #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
 #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
 #define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72)
 #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)
+#define MIDR_MICROSOFT_AZURE_COBALT_100 MIDR_CPU_MODEL(ARM_CPU_IMP_MICROSOFT, MICROSOFT_CPU_PART_AZURE_COBALT_100)
 
 /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */
 #define MIDR_FUJITSU_ERRATUM_010001            MIDR_FUJITSU_A64FX
index 89d2fc872d9f5e63dce2e2a74dfb422c9e255030..964df31da9751c96c984358c66d6f73c8519b2e7 100644 (file)
@@ -37,9 +37,7 @@
 #include <asm/ptrace.h>
 #include <asm/sve_context.h>
 
-#define __KVM_HAVE_GUEST_DEBUG
 #define __KVM_HAVE_IRQ_LINE
-#define __KVM_HAVE_READONLY_MEM
 #define __KVM_HAVE_VCPU_EVENTS
 
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
@@ -76,11 +74,11 @@ struct kvm_regs {
 
 /* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
 #define KVM_ARM_DEVICE_TYPE_SHIFT      0
-#define KVM_ARM_DEVICE_TYPE_MASK       GENMASK(KVM_ARM_DEVICE_TYPE_SHIFT + 15, \
-                                               KVM_ARM_DEVICE_TYPE_SHIFT)
+#define KVM_ARM_DEVICE_TYPE_MASK       __GENMASK(KVM_ARM_DEVICE_TYPE_SHIFT + 15, \
+                                                 KVM_ARM_DEVICE_TYPE_SHIFT)
 #define KVM_ARM_DEVICE_ID_SHIFT                16
-#define KVM_ARM_DEVICE_ID_MASK         GENMASK(KVM_ARM_DEVICE_ID_SHIFT + 15, \
-                                               KVM_ARM_DEVICE_ID_SHIFT)
+#define KVM_ARM_DEVICE_ID_MASK         __GENMASK(KVM_ARM_DEVICE_ID_SHIFT + 15, \
+                                                 KVM_ARM_DEVICE_ID_SHIFT)
 
 /* Supported device IDs */
 #define KVM_ARM_DEVICE_VGIC_V2         0
@@ -162,6 +160,11 @@ struct kvm_sync_regs {
        __u64 device_irq_level;
 };
 
+/* Bits for run->s.regs.device_irq_level */
+#define KVM_ARM_DEV_EL1_VTIMER         (1 << 0)
+#define KVM_ARM_DEV_EL1_PTIMER         (1 << 1)
+#define KVM_ARM_DEV_PMU                        (1 << 2)
+
 /*
  * PMU filter structure. Describe a range of events with a particular
  * action. To be used with KVM_ARM_VCPU_PMU_V3_FILTER.
index 9f18fa090f1f1d08179cba6f39f7b832bbd7b95b..1691297a766a9c1a4df9384c4ff02ecd8ce21b92 100644 (file)
@@ -28,7 +28,6 @@
 #define __KVM_HAVE_PPC_SMT
 #define __KVM_HAVE_IRQCHIP
 #define __KVM_HAVE_IRQ_LINE
-#define __KVM_HAVE_GUEST_DEBUG
 
 /* Not always available, but if it is, this is the correct offset.  */
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
@@ -733,4 +732,48 @@ struct kvm_ppc_xive_eq {
 #define KVM_XIVE_TIMA_PAGE_OFFSET      0
 #define KVM_XIVE_ESB_PAGE_OFFSET       4
 
+/* for KVM_PPC_GET_PVINFO */
+
+#define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
+
+struct kvm_ppc_pvinfo {
+       /* out */
+       __u32 flags;
+       __u32 hcall[4];
+       __u8  pad[108];
+};
+
+/* for KVM_PPC_GET_SMMU_INFO */
+#define KVM_PPC_PAGE_SIZES_MAX_SZ      8
+
+struct kvm_ppc_one_page_size {
+       __u32 page_shift;       /* Page shift (or 0) */
+       __u32 pte_enc;          /* Encoding in the HPTE (>>12) */
+};
+
+struct kvm_ppc_one_seg_page_size {
+       __u32 page_shift;       /* Base page shift of segment (or 0) */
+       __u32 slb_enc;          /* SLB encoding for BookS */
+       struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ];
+};
+
+#define KVM_PPC_PAGE_SIZES_REAL                0x00000001
+#define KVM_PPC_1T_SEGMENTS            0x00000002
+#define KVM_PPC_NO_HASH                        0x00000004
+
+struct kvm_ppc_smmu_info {
+       __u64 flags;
+       __u32 slb_size;
+       __u16 data_keys;        /* # storage keys supported for data */
+       __u16 instr_keys;       /* # storage keys supported for instructions */
+       struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
+};
+
+/* for KVM_PPC_RESIZE_HPT_{PREPARE,COMMIT} */
+struct kvm_ppc_resize_hpt {
+       __u64 flags;
+       __u32 shift;
+       __u32 pad;
+};
+
 #endif /* __LINUX_KVM_POWERPC_H */
index abe926d43cbe0a06342f8c53f202cdd707ea1693..05eaf6db3ad4cba4269b1ce36563096eab236b1d 100644 (file)
 #include <linux/types.h>
 
 #define __KVM_S390
-#define __KVM_HAVE_GUEST_DEBUG
+
+struct kvm_s390_skeys {
+       __u64 start_gfn;
+       __u64 count;
+       __u64 skeydata_addr;
+       __u32 flags;
+       __u32 reserved[9];
+};
+
+#define KVM_S390_CMMA_PEEK (1 << 0)
+
+/**
+ * kvm_s390_cmma_log - Used for CMMA migration.
+ *
+ * Used both for input and output.
+ *
+ * @start_gfn: Guest page number to start from.
+ * @count: Size of the result buffer.
+ * @flags: Control operation mode via KVM_S390_CMMA_* flags
+ * @remaining: Used with KVM_S390_GET_CMMA_BITS. Indicates how many dirty
+ *             pages are still remaining.
+ * @mask: Used with KVM_S390_SET_CMMA_BITS. Bitmap of bits to actually set
+ *        in the PGSTE.
+ * @values: Pointer to the values buffer.
+ *
+ * Used in KVM_S390_{G,S}ET_CMMA_BITS ioctls.
+ */
+struct kvm_s390_cmma_log {
+       __u64 start_gfn;
+       __u32 count;
+       __u32 flags;
+       union {
+               __u64 remaining;
+               __u64 mask;
+       };
+       __u64 values;
+};
+
+#define KVM_S390_RESET_POR       1
+#define KVM_S390_RESET_CLEAR     2
+#define KVM_S390_RESET_SUBSYSTEM 4
+#define KVM_S390_RESET_CPU_INIT  8
+#define KVM_S390_RESET_IPL       16
+
+/* for KVM_S390_MEM_OP */
+struct kvm_s390_mem_op {
+       /* in */
+       __u64 gaddr;            /* the guest address */
+       __u64 flags;            /* flags */
+       __u32 size;             /* amount of bytes */
+       __u32 op;               /* type of operation */
+       __u64 buf;              /* buffer in userspace */
+       union {
+               struct {
+                       __u8 ar;        /* the access register number */
+                       __u8 key;       /* access key, ignored if flag unset */
+                       __u8 pad1[6];   /* ignored */
+                       __u64 old_addr; /* ignored if cmpxchg flag unset */
+               };
+               __u32 sida_offset; /* offset into the sida */
+               __u8 reserved[32]; /* ignored */
+       };
+};
+/* types for kvm_s390_mem_op->op */
+#define KVM_S390_MEMOP_LOGICAL_READ    0
+#define KVM_S390_MEMOP_LOGICAL_WRITE   1
+#define KVM_S390_MEMOP_SIDA_READ       2
+#define KVM_S390_MEMOP_SIDA_WRITE      3
+#define KVM_S390_MEMOP_ABSOLUTE_READ   4
+#define KVM_S390_MEMOP_ABSOLUTE_WRITE  5
+#define KVM_S390_MEMOP_ABSOLUTE_CMPXCHG        6
+
+/* flags for kvm_s390_mem_op->flags */
+#define KVM_S390_MEMOP_F_CHECK_ONLY            (1ULL << 0)
+#define KVM_S390_MEMOP_F_INJECT_EXCEPTION      (1ULL << 1)
+#define KVM_S390_MEMOP_F_SKEY_PROTECTION       (1ULL << 2)
+
+/* flags specifying extension support via KVM_CAP_S390_MEM_OP_EXTENSION */
+#define KVM_S390_MEMOP_EXTENSION_CAP_BASE      (1 << 0)
+#define KVM_S390_MEMOP_EXTENSION_CAP_CMPXCHG   (1 << 1)
+
+struct kvm_s390_psw {
+       __u64 mask;
+       __u64 addr;
+};
+
+/* valid values for type in kvm_s390_interrupt */
+#define KVM_S390_SIGP_STOP             0xfffe0000u
+#define KVM_S390_PROGRAM_INT           0xfffe0001u
+#define KVM_S390_SIGP_SET_PREFIX       0xfffe0002u
+#define KVM_S390_RESTART               0xfffe0003u
+#define KVM_S390_INT_PFAULT_INIT       0xfffe0004u
+#define KVM_S390_INT_PFAULT_DONE       0xfffe0005u
+#define KVM_S390_MCHK                  0xfffe1000u
+#define KVM_S390_INT_CLOCK_COMP                0xffff1004u
+#define KVM_S390_INT_CPU_TIMER         0xffff1005u
+#define KVM_S390_INT_VIRTIO            0xffff2603u
+#define KVM_S390_INT_SERVICE           0xffff2401u
+#define KVM_S390_INT_EMERGENCY         0xffff1201u
+#define KVM_S390_INT_EXTERNAL_CALL     0xffff1202u
+/* Anything below 0xfffe0000u is taken by INT_IO */
+#define KVM_S390_INT_IO(ai,cssid,ssid,schid)   \
+       (((schid)) |                           \
+        ((ssid) << 16) |                      \
+        ((cssid) << 18) |                     \
+        ((ai) << 26))
+#define KVM_S390_INT_IO_MIN            0x00000000u
+#define KVM_S390_INT_IO_MAX            0xfffdffffu
+#define KVM_S390_INT_IO_AI_MASK                0x04000000u
+
+
+struct kvm_s390_interrupt {
+       __u32 type;
+       __u32 parm;
+       __u64 parm64;
+};
+
+struct kvm_s390_io_info {
+       __u16 subchannel_id;
+       __u16 subchannel_nr;
+       __u32 io_int_parm;
+       __u32 io_int_word;
+};
+
+struct kvm_s390_ext_info {
+       __u32 ext_params;
+       __u32 pad;
+       __u64 ext_params2;
+};
+
+struct kvm_s390_pgm_info {
+       __u64 trans_exc_code;
+       __u64 mon_code;
+       __u64 per_address;
+       __u32 data_exc_code;
+       __u16 code;
+       __u16 mon_class_nr;
+       __u8 per_code;
+       __u8 per_atmid;
+       __u8 exc_access_id;
+       __u8 per_access_id;
+       __u8 op_access_id;
+#define KVM_S390_PGM_FLAGS_ILC_VALID   0x01
+#define KVM_S390_PGM_FLAGS_ILC_0       0x02
+#define KVM_S390_PGM_FLAGS_ILC_1       0x04
+#define KVM_S390_PGM_FLAGS_ILC_MASK    0x06
+#define KVM_S390_PGM_FLAGS_NO_REWIND   0x08
+       __u8 flags;
+       __u8 pad[2];
+};
+
+struct kvm_s390_prefix_info {
+       __u32 address;
+};
+
+struct kvm_s390_extcall_info {
+       __u16 code;
+};
+
+struct kvm_s390_emerg_info {
+       __u16 code;
+};
+
+#define KVM_S390_STOP_FLAG_STORE_STATUS        0x01
+struct kvm_s390_stop_info {
+       __u32 flags;
+};
+
+struct kvm_s390_mchk_info {
+       __u64 cr14;
+       __u64 mcic;
+       __u64 failing_storage_address;
+       __u32 ext_damage_code;
+       __u32 pad;
+       __u8 fixed_logout[16];
+};
+
+struct kvm_s390_irq {
+       __u64 type;
+       union {
+               struct kvm_s390_io_info io;
+               struct kvm_s390_ext_info ext;
+               struct kvm_s390_pgm_info pgm;
+               struct kvm_s390_emerg_info emerg;
+               struct kvm_s390_extcall_info extcall;
+               struct kvm_s390_prefix_info prefix;
+               struct kvm_s390_stop_info stop;
+               struct kvm_s390_mchk_info mchk;
+               char reserved[64];
+       } u;
+};
+
+struct kvm_s390_irq_state {
+       __u64 buf;
+       __u32 flags;        /* will stay unused for compatibility reasons */
+       __u32 len;
+       __u32 reserved[4];  /* will stay unused for compatibility reasons */
+};
+
+struct kvm_s390_ucas_mapping {
+       __u64 user_addr;
+       __u64 vcpu_addr;
+       __u64 length;
+};
+
+struct kvm_s390_pv_sec_parm {
+       __u64 origin;
+       __u64 length;
+};
+
+struct kvm_s390_pv_unp {
+       __u64 addr;
+       __u64 size;
+       __u64 tweak;
+};
+
+enum pv_cmd_dmp_id {
+       KVM_PV_DUMP_INIT,
+       KVM_PV_DUMP_CONFIG_STOR_STATE,
+       KVM_PV_DUMP_COMPLETE,
+       KVM_PV_DUMP_CPU,
+};
+
+struct kvm_s390_pv_dmp {
+       __u64 subcmd;
+       __u64 buff_addr;
+       __u64 buff_len;
+       __u64 gaddr;            /* For dump storage state */
+       __u64 reserved[4];
+};
+
+enum pv_cmd_info_id {
+       KVM_PV_INFO_VM,
+       KVM_PV_INFO_DUMP,
+};
+
+struct kvm_s390_pv_info_dump {
+       __u64 dump_cpu_buffer_len;
+       __u64 dump_config_mem_buffer_per_1m;
+       __u64 dump_config_finalize_len;
+};
+
+struct kvm_s390_pv_info_vm {
+       __u64 inst_calls_list[4];
+       __u64 max_cpus;
+       __u64 max_guests;
+       __u64 max_guest_addr;
+       __u64 feature_indication;
+};
+
+struct kvm_s390_pv_info_header {
+       __u32 id;
+       __u32 len_max;
+       __u32 len_written;
+       __u32 reserved;
+};
+
+struct kvm_s390_pv_info {
+       struct kvm_s390_pv_info_header header;
+       union {
+               struct kvm_s390_pv_info_dump dump;
+               struct kvm_s390_pv_info_vm vm;
+       };
+};
+
+enum pv_cmd_id {
+       KVM_PV_ENABLE,
+       KVM_PV_DISABLE,
+       KVM_PV_SET_SEC_PARMS,
+       KVM_PV_UNPACK,
+       KVM_PV_VERIFY,
+       KVM_PV_PREP_RESET,
+       KVM_PV_UNSHARE_ALL,
+       KVM_PV_INFO,
+       KVM_PV_DUMP,
+       KVM_PV_ASYNC_CLEANUP_PREPARE,
+       KVM_PV_ASYNC_CLEANUP_PERFORM,
+};
+
+struct kvm_pv_cmd {
+       __u32 cmd;      /* Command to be executed */
+       __u16 rc;       /* Ultravisor return code */
+       __u16 rrc;      /* Ultravisor return reason code */
+       __u64 data;     /* Data or address */
+       __u32 flags;    /* flags for future extensions. Must be 0 for now */
+       __u32 reserved[3];
+};
+
+struct kvm_s390_zpci_op {
+       /* in */
+       __u32 fh;               /* target device */
+       __u8  op;               /* operation to perform */
+       __u8  pad[3];
+       union {
+               /* for KVM_S390_ZPCIOP_REG_AEN */
+               struct {
+                       __u64 ibv;      /* Guest addr of interrupt bit vector */
+                       __u64 sb;       /* Guest addr of summary bit */
+                       __u32 flags;
+                       __u32 noi;      /* Number of interrupts */
+                       __u8 isc;       /* Guest interrupt subclass */
+                       __u8 sbo;       /* Offset of guest summary bit vector */
+                       __u16 pad;
+               } reg_aen;
+               __u64 reserved[8];
+       } u;
+};
+
+/* types for kvm_s390_zpci_op->op */
+#define KVM_S390_ZPCIOP_REG_AEN                0
+#define KVM_S390_ZPCIOP_DEREG_AEN      1
+
+/* flags for kvm_s390_zpci_op->u.reg_aen.flags */
+#define KVM_S390_ZPCIOP_REGAEN_HOST    (1 << 0)
 
 /* Device control API: s390-specific devices */
 #define KVM_DEV_FLIC_GET_ALL_IRQS      1
index 25160d26764b5e29c7f4e825979d6222ae15e5c4..a38f8f9ba65729125234814c08547498e4e3b8bc 100644 (file)
@@ -13,7 +13,7 @@
 /*
  * Defines x86 CPU feature bits
  */
-#define NCAPINTS                       21         /* N 32-bit words worth of info */
+#define NCAPINTS                       22         /* N 32-bit words worth of info */
 #define NBUGINTS                       2          /* N 32-bit bug flags */
 
 /*
 #define X86_FEATURE_K6_MTRR            ( 3*32+ 1) /* AMD K6 nonstandard MTRRs */
 #define X86_FEATURE_CYRIX_ARR          ( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */
 #define X86_FEATURE_CENTAUR_MCR                ( 3*32+ 3) /* Centaur MCRs (= MTRRs) */
-
-/* CPU types for specific tunings: */
 #define X86_FEATURE_K8                 ( 3*32+ 4) /* "" Opteron, Athlon64 */
-/* FREE, was #define X86_FEATURE_K7                    ( 3*32+ 5) "" Athlon */
+#define X86_FEATURE_ZEN5               ( 3*32+ 5) /* "" CPU based on Zen5 microarchitecture */
 #define X86_FEATURE_P3                 ( 3*32+ 6) /* "" P3 */
 #define X86_FEATURE_P4                 ( 3*32+ 7) /* "" P4 */
 #define X86_FEATURE_CONSTANT_TSC       ( 3*32+ 8) /* TSC ticks at a constant rate */
@@ -97,7 +95,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 */
-/* FREE, was #define X86_FEATURE_LFENCE_RDTSC          ( 3*32+18) "" LFENCE synchronizes RDTSC */
+#define X86_FEATURE_CLEAR_CPU_BUF      ( 3*32+18) /* "" Clear CPU buffers using VERW */
 #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 */
 #define X86_FEATURE_IBPB_BRTYPE                (20*32+28) /* "" MSR_PRED_CMD[IBPB] flushes all branch type predictions */
 #define X86_FEATURE_SRSO_NO            (20*32+29) /* "" CPU is not affected by SRSO */
 
+/*
+ * Extended auxiliary flags: Linux defined - for features scattered in various
+ * CPUID levels like 0x80000022, etc.
+ *
+ * Reuse free bits when adding new feature flags!
+ */
+#define X86_FEATURE_AMD_LBR_PMC_FREEZE (21*32+ 0) /* AMD LBR and PMC Freeze */
+
 /*
  * BUG word(s)
  */
 /* BUG word 2 */
 #define X86_BUG_SRSO                   X86_BUG(1*32 + 0) /* AMD SRSO bug */
 #define X86_BUG_DIV0                   X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */
+#define X86_BUG_RFDS                   X86_BUG(1*32 + 2) /* CPU is vulnerable to Register File Data Sampling */
 #endif /* _ASM_X86_CPUFEATURES_H */
index 1f23960d2b06e7bea48be6f7213e678962626e99..c492bdc97b0595ec77f89dc9b0cefe5e3e64be41 100644 (file)
 # define DISABLE_FRED  (1 << (X86_FEATURE_FRED & 31))
 #endif
 
+#ifdef CONFIG_KVM_AMD_SEV
+#define DISABLE_SEV_SNP                0
+#else
+#define DISABLE_SEV_SNP                (1 << (X86_FEATURE_SEV_SNP & 31))
+#endif
+
 /*
  * Make sure to add features to the correct mask
  */
                         DISABLE_ENQCMD)
 #define DISABLED_MASK17        0
 #define DISABLED_MASK18        (DISABLE_IBT)
-#define DISABLED_MASK19        0
+#define DISABLED_MASK19        (DISABLE_SEV_SNP)
 #define DISABLED_MASK20        0
-#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 21)
+#define DISABLED_MASK21        0
+#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 22)
 
 #endif /* _ASM_X86_DISABLED_FEATURES_H */
index 3f73ac3ed3a0709a700ae927bca01069a1910665..d18bfb238f660fcccdfdf444a60720f03163e4d5 100644 (file)
 #define HYPERVISOR_CALLBACK_VECTOR     0xf3
 
 /* Vector for KVM to deliver posted interrupt IPI */
-#if IS_ENABLED(CONFIG_KVM)
 #define POSTED_INTR_VECTOR             0xf2
 #define POSTED_INTR_WAKEUP_VECTOR      0xf1
 #define POSTED_INTR_NESTED_VECTOR      0xf0
-#endif
 
 #define MANAGED_IRQ_SHUTDOWN_VECTOR    0xef
 
index 1f9dc9bd13eb7e9c7bc509b1d09cec7f473157b4..05956bd8bacf50e35f463c13720a38735fe8b1b5 100644 (file)
                                                 * CPU is not vulnerable to Gather
                                                 * Data Sampling (GDS).
                                                 */
+#define ARCH_CAP_RFDS_NO               BIT(27) /*
+                                                * Not susceptible to Register
+                                                * File Data Sampling.
+                                                */
+#define ARCH_CAP_RFDS_CLEAR            BIT(28) /*
+                                                * VERW clears CPU Register
+                                                * File.
+                                                */
 
 #define ARCH_CAP_XAPIC_DISABLE         BIT(21) /*
                                                 * IA32_XAPIC_DISABLE_STATUS MSR
 #define MSR_AMD64_SEV_ES_GHCB          0xc0010130
 #define MSR_AMD64_SEV                  0xc0010131
 #define MSR_AMD64_SEV_ENABLED_BIT      0
-#define MSR_AMD64_SEV_ES_ENABLED_BIT   1
-#define MSR_AMD64_SEV_SNP_ENABLED_BIT  2
 #define MSR_AMD64_SEV_ENABLED          BIT_ULL(MSR_AMD64_SEV_ENABLED_BIT)
+#define MSR_AMD64_SEV_ES_ENABLED_BIT   1
 #define MSR_AMD64_SEV_ES_ENABLED       BIT_ULL(MSR_AMD64_SEV_ES_ENABLED_BIT)
+#define MSR_AMD64_SEV_SNP_ENABLED_BIT  2
 #define MSR_AMD64_SEV_SNP_ENABLED      BIT_ULL(MSR_AMD64_SEV_SNP_ENABLED_BIT)
-
-/* SNP feature bits enabled by the hypervisor */
-#define MSR_AMD64_SNP_VTOM                     BIT_ULL(3)
-#define MSR_AMD64_SNP_REFLECT_VC               BIT_ULL(4)
-#define MSR_AMD64_SNP_RESTRICTED_INJ           BIT_ULL(5)
-#define MSR_AMD64_SNP_ALT_INJ                  BIT_ULL(6)
-#define MSR_AMD64_SNP_DEBUG_SWAP               BIT_ULL(7)
-#define MSR_AMD64_SNP_PREVENT_HOST_IBS         BIT_ULL(8)
-#define MSR_AMD64_SNP_BTB_ISOLATION            BIT_ULL(9)
-#define MSR_AMD64_SNP_VMPL_SSS                 BIT_ULL(10)
-#define MSR_AMD64_SNP_SECURE_TSC               BIT_ULL(11)
-#define MSR_AMD64_SNP_VMGEXIT_PARAM            BIT_ULL(12)
-#define MSR_AMD64_SNP_IBS_VIRT                 BIT_ULL(14)
-#define MSR_AMD64_SNP_VMSA_REG_PROTECTION      BIT_ULL(16)
-#define MSR_AMD64_SNP_SMT_PROTECTION           BIT_ULL(17)
-
-/* SNP feature bits reserved for future use. */
-#define MSR_AMD64_SNP_RESERVED_BIT13           BIT_ULL(13)
-#define MSR_AMD64_SNP_RESERVED_BIT15           BIT_ULL(15)
-#define MSR_AMD64_SNP_RESERVED_MASK            GENMASK_ULL(63, 18)
+#define MSR_AMD64_SNP_VTOM_BIT         3
+#define MSR_AMD64_SNP_VTOM             BIT_ULL(MSR_AMD64_SNP_VTOM_BIT)
+#define MSR_AMD64_SNP_REFLECT_VC_BIT   4
+#define MSR_AMD64_SNP_REFLECT_VC       BIT_ULL(MSR_AMD64_SNP_REFLECT_VC_BIT)
+#define MSR_AMD64_SNP_RESTRICTED_INJ_BIT 5
+#define MSR_AMD64_SNP_RESTRICTED_INJ   BIT_ULL(MSR_AMD64_SNP_RESTRICTED_INJ_BIT)
+#define MSR_AMD64_SNP_ALT_INJ_BIT      6
+#define MSR_AMD64_SNP_ALT_INJ          BIT_ULL(MSR_AMD64_SNP_ALT_INJ_BIT)
+#define MSR_AMD64_SNP_DEBUG_SWAP_BIT   7
+#define MSR_AMD64_SNP_DEBUG_SWAP       BIT_ULL(MSR_AMD64_SNP_DEBUG_SWAP_BIT)
+#define MSR_AMD64_SNP_PREVENT_HOST_IBS_BIT 8
+#define MSR_AMD64_SNP_PREVENT_HOST_IBS BIT_ULL(MSR_AMD64_SNP_PREVENT_HOST_IBS_BIT)
+#define MSR_AMD64_SNP_BTB_ISOLATION_BIT        9
+#define MSR_AMD64_SNP_BTB_ISOLATION    BIT_ULL(MSR_AMD64_SNP_BTB_ISOLATION_BIT)
+#define MSR_AMD64_SNP_VMPL_SSS_BIT     10
+#define MSR_AMD64_SNP_VMPL_SSS         BIT_ULL(MSR_AMD64_SNP_VMPL_SSS_BIT)
+#define MSR_AMD64_SNP_SECURE_TSC_BIT   11
+#define MSR_AMD64_SNP_SECURE_TSC       BIT_ULL(MSR_AMD64_SNP_SECURE_TSC_BIT)
+#define MSR_AMD64_SNP_VMGEXIT_PARAM_BIT        12
+#define MSR_AMD64_SNP_VMGEXIT_PARAM    BIT_ULL(MSR_AMD64_SNP_VMGEXIT_PARAM_BIT)
+#define MSR_AMD64_SNP_RESERVED_BIT13   BIT_ULL(13)
+#define MSR_AMD64_SNP_IBS_VIRT_BIT     14
+#define MSR_AMD64_SNP_IBS_VIRT         BIT_ULL(MSR_AMD64_SNP_IBS_VIRT_BIT)
+#define MSR_AMD64_SNP_RESERVED_BIT15   BIT_ULL(15)
+#define MSR_AMD64_SNP_VMSA_REG_PROT_BIT        16
+#define MSR_AMD64_SNP_VMSA_REG_PROT    BIT_ULL(MSR_AMD64_SNP_VMSA_REG_PROT_BIT)
+#define MSR_AMD64_SNP_SMT_PROT_BIT     17
+#define MSR_AMD64_SNP_SMT_PROT         BIT_ULL(MSR_AMD64_SNP_SMT_PROT_BIT)
+#define MSR_AMD64_SNP_RESV_BIT         18
+#define MSR_AMD64_SNP_RESERVED_MASK    GENMASK_ULL(63, MSR_AMD64_SNP_RESV_BIT)
 
 #define MSR_AMD64_VIRT_SPEC_CTRL       0xc001011f
 
+#define MSR_AMD64_RMP_BASE             0xc0010132
+#define MSR_AMD64_RMP_END              0xc0010133
+
 /* AMD Collaborative Processor Performance Control MSRs */
 #define MSR_AMD_CPPC_CAP1              0xc00102b0
 #define MSR_AMD_CPPC_ENABLE            0xc00102b1
 #define MSR_K8_TOP_MEM1                        0xc001001a
 #define MSR_K8_TOP_MEM2                        0xc001001d
 #define MSR_AMD64_SYSCFG               0xc0010010
-#define MSR_AMD64_SYSCFG_MEM_ENCRYPT_BIT       23
+#define MSR_AMD64_SYSCFG_MEM_ENCRYPT_BIT 23
 #define MSR_AMD64_SYSCFG_MEM_ENCRYPT   BIT_ULL(MSR_AMD64_SYSCFG_MEM_ENCRYPT_BIT)
+#define MSR_AMD64_SYSCFG_SNP_EN_BIT    24
+#define MSR_AMD64_SYSCFG_SNP_EN                BIT_ULL(MSR_AMD64_SYSCFG_SNP_EN_BIT)
+#define MSR_AMD64_SYSCFG_SNP_VMPL_EN_BIT 25
+#define MSR_AMD64_SYSCFG_SNP_VMPL_EN   BIT_ULL(MSR_AMD64_SYSCFG_SNP_VMPL_EN_BIT)
+#define MSR_AMD64_SYSCFG_MFDM_BIT      19
+#define MSR_AMD64_SYSCFG_MFDM          BIT_ULL(MSR_AMD64_SYSCFG_MFDM_BIT)
+
 #define MSR_K8_INT_PENDING_MSG         0xc0010055
 /* C1E active bits in int pending message */
 #define K8_INTP_C1E_ACTIVE_MASK                0x18000000
index 7ba1726b71c7b8bfc95888dc78508998bba263fe..e9187ddd3d1fdc61fff087b0ea3b8b9b0ff33ac3 100644 (file)
@@ -99,6 +99,7 @@
 #define REQUIRED_MASK18        0
 #define REQUIRED_MASK19        0
 #define REQUIRED_MASK20        0
-#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 21)
+#define REQUIRED_MASK21        0
+#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 22)
 
 #endif /* _ASM_X86_REQUIRED_FEATURES_H */
index a448d0964fc06ebd0c15cd0b550e3c2cefbf57bf..ef11aa4cab42536cf1773bf5b787bcf715bd76e9 100644 (file)
@@ -7,6 +7,8 @@
  *
  */
 
+#include <linux/const.h>
+#include <linux/bits.h>
 #include <linux/types.h>
 #include <linux/ioctl.h>
 #include <linux/stddef.h>
@@ -40,7 +42,6 @@
 #define __KVM_HAVE_IRQ_LINE
 #define __KVM_HAVE_MSI
 #define __KVM_HAVE_USER_NMI
-#define __KVM_HAVE_GUEST_DEBUG
 #define __KVM_HAVE_MSIX
 #define __KVM_HAVE_MCE
 #define __KVM_HAVE_PIT_STATE2
@@ -49,7 +50,6 @@
 #define __KVM_HAVE_DEBUGREGS
 #define __KVM_HAVE_XSAVE
 #define __KVM_HAVE_XCRS
-#define __KVM_HAVE_READONLY_MEM
 
 /* Architectural interrupt line count. */
 #define KVM_NR_INTERRUPTS 256
@@ -526,9 +526,301 @@ struct kvm_pmu_event_filter {
 #define KVM_PMU_EVENT_ALLOW 0
 #define KVM_PMU_EVENT_DENY 1
 
-#define KVM_PMU_EVENT_FLAG_MASKED_EVENTS BIT(0)
+#define KVM_PMU_EVENT_FLAG_MASKED_EVENTS _BITUL(0)
 #define KVM_PMU_EVENT_FLAGS_VALID_MASK (KVM_PMU_EVENT_FLAG_MASKED_EVENTS)
 
+/* for KVM_CAP_MCE */
+struct kvm_x86_mce {
+       __u64 status;
+       __u64 addr;
+       __u64 misc;
+       __u64 mcg_status;
+       __u8 bank;
+       __u8 pad1[7];
+       __u64 pad2[3];
+};
+
+/* for KVM_CAP_XEN_HVM */
+#define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR       (1 << 0)
+#define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL     (1 << 1)
+#define KVM_XEN_HVM_CONFIG_SHARED_INFO         (1 << 2)
+#define KVM_XEN_HVM_CONFIG_RUNSTATE            (1 << 3)
+#define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL       (1 << 4)
+#define KVM_XEN_HVM_CONFIG_EVTCHN_SEND         (1 << 5)
+#define KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG        (1 << 6)
+#define KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE        (1 << 7)
+#define KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA     (1 << 8)
+
+struct kvm_xen_hvm_config {
+       __u32 flags;
+       __u32 msr;
+       __u64 blob_addr_32;
+       __u64 blob_addr_64;
+       __u8 blob_size_32;
+       __u8 blob_size_64;
+       __u8 pad2[30];
+};
+
+struct kvm_xen_hvm_attr {
+       __u16 type;
+       __u16 pad[3];
+       union {
+               __u8 long_mode;
+               __u8 vector;
+               __u8 runstate_update_flag;
+               union {
+                       __u64 gfn;
+#define KVM_XEN_INVALID_GFN ((__u64)-1)
+                       __u64 hva;
+               } shared_info;
+               struct {
+                       __u32 send_port;
+                       __u32 type; /* EVTCHNSTAT_ipi / EVTCHNSTAT_interdomain */
+                       __u32 flags;
+#define KVM_XEN_EVTCHN_DEASSIGN                (1 << 0)
+#define KVM_XEN_EVTCHN_UPDATE          (1 << 1)
+#define KVM_XEN_EVTCHN_RESET           (1 << 2)
+                       /*
+                        * Events sent by the guest are either looped back to
+                        * the guest itself (potentially on a different port#)
+                        * or signalled via an eventfd.
+                        */
+                       union {
+                               struct {
+                                       __u32 port;
+                                       __u32 vcpu;
+                                       __u32 priority;
+                               } port;
+                               struct {
+                                       __u32 port; /* Zero for eventfd */
+                                       __s32 fd;
+                               } eventfd;
+                               __u32 padding[4];
+                       } deliver;
+               } evtchn;
+               __u32 xen_version;
+               __u64 pad[8];
+       } u;
+};
+
+
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */
+#define KVM_XEN_ATTR_TYPE_LONG_MODE            0x0
+#define KVM_XEN_ATTR_TYPE_SHARED_INFO          0x1
+#define KVM_XEN_ATTR_TYPE_UPCALL_VECTOR                0x2
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */
+#define KVM_XEN_ATTR_TYPE_EVTCHN               0x3
+#define KVM_XEN_ATTR_TYPE_XEN_VERSION          0x4
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG */
+#define KVM_XEN_ATTR_TYPE_RUNSTATE_UPDATE_FLAG 0x5
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA */
+#define KVM_XEN_ATTR_TYPE_SHARED_INFO_HVA      0x6
+
+struct kvm_xen_vcpu_attr {
+       __u16 type;
+       __u16 pad[3];
+       union {
+               __u64 gpa;
+#define KVM_XEN_INVALID_GPA ((__u64)-1)
+               __u64 hva;
+               __u64 pad[8];
+               struct {
+                       __u64 state;
+                       __u64 state_entry_time;
+                       __u64 time_running;
+                       __u64 time_runnable;
+                       __u64 time_blocked;
+                       __u64 time_offline;
+               } runstate;
+               __u32 vcpu_id;
+               struct {
+                       __u32 port;
+                       __u32 priority;
+                       __u64 expires_ns;
+               } timer;
+               __u8 vector;
+       } u;
+};
+
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */
+#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO       0x0
+#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO  0x1
+#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR   0x2
+#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT        0x3
+#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA   0x4
+#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 0x5
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */
+#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID         0x6
+#define KVM_XEN_VCPU_ATTR_TYPE_TIMER           0x7
+#define KVM_XEN_VCPU_ATTR_TYPE_UPCALL_VECTOR   0x8
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA */
+#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO_HVA   0x9
+
+/* Secure Encrypted Virtualization command */
+enum sev_cmd_id {
+       /* Guest initialization commands */
+       KVM_SEV_INIT = 0,
+       KVM_SEV_ES_INIT,
+       /* Guest launch commands */
+       KVM_SEV_LAUNCH_START,
+       KVM_SEV_LAUNCH_UPDATE_DATA,
+       KVM_SEV_LAUNCH_UPDATE_VMSA,
+       KVM_SEV_LAUNCH_SECRET,
+       KVM_SEV_LAUNCH_MEASURE,
+       KVM_SEV_LAUNCH_FINISH,
+       /* Guest migration commands (outgoing) */
+       KVM_SEV_SEND_START,
+       KVM_SEV_SEND_UPDATE_DATA,
+       KVM_SEV_SEND_UPDATE_VMSA,
+       KVM_SEV_SEND_FINISH,
+       /* Guest migration commands (incoming) */
+       KVM_SEV_RECEIVE_START,
+       KVM_SEV_RECEIVE_UPDATE_DATA,
+       KVM_SEV_RECEIVE_UPDATE_VMSA,
+       KVM_SEV_RECEIVE_FINISH,
+       /* Guest status and debug commands */
+       KVM_SEV_GUEST_STATUS,
+       KVM_SEV_DBG_DECRYPT,
+       KVM_SEV_DBG_ENCRYPT,
+       /* Guest certificates commands */
+       KVM_SEV_CERT_EXPORT,
+       /* Attestation report */
+       KVM_SEV_GET_ATTESTATION_REPORT,
+       /* Guest Migration Extension */
+       KVM_SEV_SEND_CANCEL,
+
+       KVM_SEV_NR_MAX,
+};
+
+struct kvm_sev_cmd {
+       __u32 id;
+       __u32 pad0;
+       __u64 data;
+       __u32 error;
+       __u32 sev_fd;
+};
+
+struct kvm_sev_launch_start {
+       __u32 handle;
+       __u32 policy;
+       __u64 dh_uaddr;
+       __u32 dh_len;
+       __u32 pad0;
+       __u64 session_uaddr;
+       __u32 session_len;
+       __u32 pad1;
+};
+
+struct kvm_sev_launch_update_data {
+       __u64 uaddr;
+       __u32 len;
+       __u32 pad0;
+};
+
+
+struct kvm_sev_launch_secret {
+       __u64 hdr_uaddr;
+       __u32 hdr_len;
+       __u32 pad0;
+       __u64 guest_uaddr;
+       __u32 guest_len;
+       __u32 pad1;
+       __u64 trans_uaddr;
+       __u32 trans_len;
+       __u32 pad2;
+};
+
+struct kvm_sev_launch_measure {
+       __u64 uaddr;
+       __u32 len;
+       __u32 pad0;
+};
+
+struct kvm_sev_guest_status {
+       __u32 handle;
+       __u32 policy;
+       __u32 state;
+};
+
+struct kvm_sev_dbg {
+       __u64 src_uaddr;
+       __u64 dst_uaddr;
+       __u32 len;
+       __u32 pad0;
+};
+
+struct kvm_sev_attestation_report {
+       __u8 mnonce[16];
+       __u64 uaddr;
+       __u32 len;
+       __u32 pad0;
+};
+
+struct kvm_sev_send_start {
+       __u32 policy;
+       __u32 pad0;
+       __u64 pdh_cert_uaddr;
+       __u32 pdh_cert_len;
+       __u32 pad1;
+       __u64 plat_certs_uaddr;
+       __u32 plat_certs_len;
+       __u32 pad2;
+       __u64 amd_certs_uaddr;
+       __u32 amd_certs_len;
+       __u32 pad3;
+       __u64 session_uaddr;
+       __u32 session_len;
+       __u32 pad4;
+};
+
+struct kvm_sev_send_update_data {
+       __u64 hdr_uaddr;
+       __u32 hdr_len;
+       __u32 pad0;
+       __u64 guest_uaddr;
+       __u32 guest_len;
+       __u32 pad1;
+       __u64 trans_uaddr;
+       __u32 trans_len;
+       __u32 pad2;
+};
+
+struct kvm_sev_receive_start {
+       __u32 handle;
+       __u32 policy;
+       __u64 pdh_uaddr;
+       __u32 pdh_len;
+       __u32 pad0;
+       __u64 session_uaddr;
+       __u32 session_len;
+       __u32 pad1;
+};
+
+struct kvm_sev_receive_update_data {
+       __u64 hdr_uaddr;
+       __u32 hdr_len;
+       __u32 pad0;
+       __u64 guest_uaddr;
+       __u32 guest_len;
+       __u32 pad1;
+       __u64 trans_uaddr;
+       __u32 trans_len;
+       __u32 pad2;
+};
+
+#define KVM_X2APIC_API_USE_32BIT_IDS            (1ULL << 0)
+#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK  (1ULL << 1)
+
+struct kvm_hyperv_eventfd {
+       __u32 conn_id;
+       __s32 fd;
+       __u32 flags;
+       __u32 padding[3];
+};
+
+#define KVM_HYPERV_CONN_ID_MASK                0x00ffffff
+#define KVM_HYPERV_EVENTFD_DEASSIGN    (1 << 0)
+
 /*
  * Masked event layout.
  * Bits   Description
@@ -549,10 +841,10 @@ struct kvm_pmu_event_filter {
        ((__u64)(!!(exclude)) << 55))
 
 #define KVM_PMU_MASKED_ENTRY_EVENT_SELECT \
-       (GENMASK_ULL(7, 0) | GENMASK_ULL(35, 32))
-#define KVM_PMU_MASKED_ENTRY_UMASK_MASK                (GENMASK_ULL(63, 56))
-#define KVM_PMU_MASKED_ENTRY_UMASK_MATCH       (GENMASK_ULL(15, 8))
-#define KVM_PMU_MASKED_ENTRY_EXCLUDE           (BIT_ULL(55))
+       (__GENMASK_ULL(7, 0) | __GENMASK_ULL(35, 32))
+#define KVM_PMU_MASKED_ENTRY_UMASK_MASK                (__GENMASK_ULL(63, 56))
+#define KVM_PMU_MASKED_ENTRY_UMASK_MATCH       (__GENMASK_ULL(15, 8))
+#define KVM_PMU_MASKED_ENTRY_EXCLUDE           (_BITULL(55))
 #define KVM_PMU_MASKED_ENTRY_UMASK_MASK_SHIFT  (56)
 
 /* for KVM_{GET,SET,HAS}_DEVICE_ATTR */
@@ -560,7 +852,7 @@ struct kvm_pmu_event_filter {
 #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)
+#define KVM_EXIT_HYPERCALL_LONG_MODE   _BITULL(0)
 
 #define KVM_X86_DEFAULT_VM     0
 #define KVM_X86_SW_PROTECTED_VM        1
index 03f721a8a2b1993734e458399a68848637112c87..54ccccf96e21eaad9cf4a681d304ad8ac689f371 100644 (file)
@@ -5,12 +5,12 @@
 #include <asm/types.h>
 
 /**
- * __fls - find last (most-significant) set bit in a long word
+ * generic___fls - find last (most-significant) set bit in a long word
  * @word: the word to search
  *
  * Undefined if no set bit exists, so code should check against 0 first.
  */
-static __always_inline unsigned long __fls(unsigned long word)
+static __always_inline unsigned long generic___fls(unsigned long word)
 {
        int num = BITS_PER_LONG - 1;
 
@@ -41,4 +41,8 @@ static __always_inline unsigned long __fls(unsigned long word)
        return num;
 }
 
+#ifndef __HAVE_ARCH___FLS
+#define __fls(word) generic___fls(word)
+#endif
+
 #endif /* _ASM_GENERIC_BITOPS___FLS_H_ */
index b168bb10e1be17bb6394e749c238da3940ea3a01..26f3ce1dd6e44872000d7066d4b3e37325e915fa 100644 (file)
@@ -3,14 +3,14 @@
 #define _ASM_GENERIC_BITOPS_FLS_H_
 
 /**
- * fls - find last (most-significant) bit set
+ * generic_fls - find last (most-significant) bit set
  * @x: the word to search
  *
  * This is defined the same way as ffs.
  * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
  */
 
-static __always_inline int fls(unsigned int x)
+static __always_inline int generic_fls(unsigned int x)
 {
        int r = 32;
 
@@ -39,4 +39,8 @@ static __always_inline int fls(unsigned int x)
        return r;
 }
 
+#ifndef __HAVE_ARCH_FLS
+#define fls(x) generic_fls(x)
+#endif
+
 #endif /* _ASM_GENERIC_BITOPS_FLS_H_ */
index fd4f9574d177a269b2cdbe5a36b3b30f2addbc94..2ee338860b7e08c80fb9f0a65702dc1b18456b6b 100644 (file)
@@ -3013,6 +3013,7 @@ struct drm_i915_query_item {
         *  - %DRM_I915_QUERY_MEMORY_REGIONS (see struct drm_i915_query_memory_regions)
         *  - %DRM_I915_QUERY_HWCONFIG_BLOB (see `GuC HWCONFIG blob uAPI`)
         *  - %DRM_I915_QUERY_GEOMETRY_SUBSLICES (see struct drm_i915_query_topology_info)
+        *  - %DRM_I915_QUERY_GUC_SUBMISSION_VERSION (see struct drm_i915_query_guc_submission_version)
         */
        __u64 query_id;
 #define DRM_I915_QUERY_TOPOLOGY_INFO           1
@@ -3021,6 +3022,7 @@ struct drm_i915_query_item {
 #define DRM_I915_QUERY_MEMORY_REGIONS          4
 #define DRM_I915_QUERY_HWCONFIG_BLOB           5
 #define DRM_I915_QUERY_GEOMETRY_SUBSLICES      6
+#define DRM_I915_QUERY_GUC_SUBMISSION_VERSION  7
 /* Must be kept compact -- no holes and well documented */
 
        /**
@@ -3566,6 +3568,20 @@ struct drm_i915_query_memory_regions {
        struct drm_i915_memory_region_info regions[];
 };
 
+/**
+ * struct drm_i915_query_guc_submission_version - query GuC submission interface version
+ */
+struct drm_i915_query_guc_submission_version {
+       /** @branch: Firmware branch version. */
+       __u32 branch;
+       /** @major: Firmware major version. */
+       __u32 major;
+       /** @minor: Firmware minor version. */
+       __u32 minor;
+       /** @patch: Firmware patch version. */
+       __u32 patch;
+};
+
 /**
  * DOC: GuC HWCONFIG blob uAPI
  *
index 48ad69f7722e1ae51ae5871a06482b6aa45dfc18..45e4e64fd6643ce3a83711cb295c711dd67ca511 100644 (file)
@@ -64,6 +64,24 @@ struct fstrim_range {
        __u64 minlen;
 };
 
+/*
+ * We include a length field because some filesystems (vfat) have an identifier
+ * that we do want to expose as a UUID, but doesn't have the standard length.
+ *
+ * We use a fixed size buffer beacuse this interface will, by fiat, never
+ * support "UUIDs" longer than 16 bytes; we don't want to force all downstream
+ * users to have to deal with that.
+ */
+struct fsuuid2 {
+       __u8    len;
+       __u8    uuid[16];
+};
+
+struct fs_sysfs_path {
+       __u8                    len;
+       __u8                    name[128];
+};
+
 /* extent-same (dedupe) ioctls; these MUST match the btrfs ioctl definitions */
 #define FILE_DEDUPE_RANGE_SAME         0
 #define FILE_DEDUPE_RANGE_DIFFERS      1
@@ -215,6 +233,13 @@ struct fsxattr {
 #define FS_IOC_FSSETXATTR              _IOW('X', 32, struct fsxattr)
 #define FS_IOC_GETFSLABEL              _IOR(0x94, 49, char[FSLABEL_MAX])
 #define FS_IOC_SETFSLABEL              _IOW(0x94, 50, char[FSLABEL_MAX])
+/* Returns the external filesystem UUID, the same one blkid returns */
+#define FS_IOC_GETFSUUID               _IOR(0x15, 0, struct fsuuid2)
+/*
+ * Returns the path component under /sys/fs/ that refers to this filesystem;
+ * also /sys/kernel/debug/ for filesystems with debugfs exports
+ */
+#define FS_IOC_GETFSSYSFSPATH          _IOR(0x15, 1, struct fs_sysfs_path)
 
 /*
  * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS)
@@ -301,9 +326,12 @@ typedef int __bitwise __kernel_rwf_t;
 /* per-IO O_APPEND */
 #define RWF_APPEND     ((__force __kernel_rwf_t)0x00000010)
 
+/* per-IO negation of O_APPEND */
+#define RWF_NOAPPEND   ((__force __kernel_rwf_t)0x00000020)
+
 /* mask of flags supported by the kernel */
 #define RWF_SUPPORTED  (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT |\
-                        RWF_APPEND)
+                        RWF_APPEND | RWF_NOAPPEND)
 
 /* Pagemap ioctl */
 #define PAGEMAP_SCAN   _IOWR('f', 16, struct pm_scan_arg)
index c3308536482bdb2bfb1279279325faf5430a3356..2190adbe30027cec3bd88bdf7c4366cd7c424b82 100644 (file)
 
 #define KVM_API_VERSION 12
 
+/*
+ * Backwards-compatible definitions.
+ */
+#define __KVM_HAVE_GUEST_DEBUG
+
 /* for KVM_SET_USER_MEMORY_REGION */
 struct kvm_userspace_memory_region {
        __u32 slot;
@@ -85,43 +90,6 @@ struct kvm_pit_config {
 
 #define KVM_PIT_SPEAKER_DUMMY     1
 
-struct kvm_s390_skeys {
-       __u64 start_gfn;
-       __u64 count;
-       __u64 skeydata_addr;
-       __u32 flags;
-       __u32 reserved[9];
-};
-
-#define KVM_S390_CMMA_PEEK (1 << 0)
-
-/**
- * kvm_s390_cmma_log - Used for CMMA migration.
- *
- * Used both for input and output.
- *
- * @start_gfn: Guest page number to start from.
- * @count: Size of the result buffer.
- * @flags: Control operation mode via KVM_S390_CMMA_* flags
- * @remaining: Used with KVM_S390_GET_CMMA_BITS. Indicates how many dirty
- *             pages are still remaining.
- * @mask: Used with KVM_S390_SET_CMMA_BITS. Bitmap of bits to actually set
- *        in the PGSTE.
- * @values: Pointer to the values buffer.
- *
- * Used in KVM_S390_{G,S}ET_CMMA_BITS ioctls.
- */
-struct kvm_s390_cmma_log {
-       __u64 start_gfn;
-       __u32 count;
-       __u32 flags;
-       union {
-               __u64 remaining;
-               __u64 mask;
-       };
-       __u64 values;
-};
-
 struct kvm_hyperv_exit {
 #define KVM_EXIT_HYPERV_SYNIC          1
 #define KVM_EXIT_HYPERV_HCALL          2
@@ -315,11 +283,6 @@ struct kvm_run {
                        __u32 ipb;
                } s390_sieic;
                /* KVM_EXIT_S390_RESET */
-#define KVM_S390_RESET_POR       1
-#define KVM_S390_RESET_CLEAR     2
-#define KVM_S390_RESET_SUBSYSTEM 4
-#define KVM_S390_RESET_CPU_INIT  8
-#define KVM_S390_RESET_IPL       16
                __u64 s390_reset_flags;
                /* KVM_EXIT_S390_UCONTROL */
                struct {
@@ -536,43 +499,6 @@ struct kvm_translation {
        __u8  pad[5];
 };
 
-/* for KVM_S390_MEM_OP */
-struct kvm_s390_mem_op {
-       /* in */
-       __u64 gaddr;            /* the guest address */
-       __u64 flags;            /* flags */
-       __u32 size;             /* amount of bytes */
-       __u32 op;               /* type of operation */
-       __u64 buf;              /* buffer in userspace */
-       union {
-               struct {
-                       __u8 ar;        /* the access register number */
-                       __u8 key;       /* access key, ignored if flag unset */
-                       __u8 pad1[6];   /* ignored */
-                       __u64 old_addr; /* ignored if cmpxchg flag unset */
-               };
-               __u32 sida_offset; /* offset into the sida */
-               __u8 reserved[32]; /* ignored */
-       };
-};
-/* types for kvm_s390_mem_op->op */
-#define KVM_S390_MEMOP_LOGICAL_READ    0
-#define KVM_S390_MEMOP_LOGICAL_WRITE   1
-#define KVM_S390_MEMOP_SIDA_READ       2
-#define KVM_S390_MEMOP_SIDA_WRITE      3
-#define KVM_S390_MEMOP_ABSOLUTE_READ   4
-#define KVM_S390_MEMOP_ABSOLUTE_WRITE  5
-#define KVM_S390_MEMOP_ABSOLUTE_CMPXCHG        6
-
-/* flags for kvm_s390_mem_op->flags */
-#define KVM_S390_MEMOP_F_CHECK_ONLY            (1ULL << 0)
-#define KVM_S390_MEMOP_F_INJECT_EXCEPTION      (1ULL << 1)
-#define KVM_S390_MEMOP_F_SKEY_PROTECTION       (1ULL << 2)
-
-/* flags specifying extension support via KVM_CAP_S390_MEM_OP_EXTENSION */
-#define KVM_S390_MEMOP_EXTENSION_CAP_BASE      (1 << 0)
-#define KVM_S390_MEMOP_EXTENSION_CAP_CMPXCHG   (1 << 1)
-
 /* for KVM_INTERRUPT */
 struct kvm_interrupt {
        /* in */
@@ -637,124 +563,6 @@ struct kvm_mp_state {
        __u32 mp_state;
 };
 
-struct kvm_s390_psw {
-       __u64 mask;
-       __u64 addr;
-};
-
-/* valid values for type in kvm_s390_interrupt */
-#define KVM_S390_SIGP_STOP             0xfffe0000u
-#define KVM_S390_PROGRAM_INT           0xfffe0001u
-#define KVM_S390_SIGP_SET_PREFIX       0xfffe0002u
-#define KVM_S390_RESTART               0xfffe0003u
-#define KVM_S390_INT_PFAULT_INIT       0xfffe0004u
-#define KVM_S390_INT_PFAULT_DONE       0xfffe0005u
-#define KVM_S390_MCHK                  0xfffe1000u
-#define KVM_S390_INT_CLOCK_COMP                0xffff1004u
-#define KVM_S390_INT_CPU_TIMER         0xffff1005u
-#define KVM_S390_INT_VIRTIO            0xffff2603u
-#define KVM_S390_INT_SERVICE           0xffff2401u
-#define KVM_S390_INT_EMERGENCY         0xffff1201u
-#define KVM_S390_INT_EXTERNAL_CALL     0xffff1202u
-/* Anything below 0xfffe0000u is taken by INT_IO */
-#define KVM_S390_INT_IO(ai,cssid,ssid,schid)   \
-       (((schid)) |                           \
-        ((ssid) << 16) |                      \
-        ((cssid) << 18) |                     \
-        ((ai) << 26))
-#define KVM_S390_INT_IO_MIN            0x00000000u
-#define KVM_S390_INT_IO_MAX            0xfffdffffu
-#define KVM_S390_INT_IO_AI_MASK                0x04000000u
-
-
-struct kvm_s390_interrupt {
-       __u32 type;
-       __u32 parm;
-       __u64 parm64;
-};
-
-struct kvm_s390_io_info {
-       __u16 subchannel_id;
-       __u16 subchannel_nr;
-       __u32 io_int_parm;
-       __u32 io_int_word;
-};
-
-struct kvm_s390_ext_info {
-       __u32 ext_params;
-       __u32 pad;
-       __u64 ext_params2;
-};
-
-struct kvm_s390_pgm_info {
-       __u64 trans_exc_code;
-       __u64 mon_code;
-       __u64 per_address;
-       __u32 data_exc_code;
-       __u16 code;
-       __u16 mon_class_nr;
-       __u8 per_code;
-       __u8 per_atmid;
-       __u8 exc_access_id;
-       __u8 per_access_id;
-       __u8 op_access_id;
-#define KVM_S390_PGM_FLAGS_ILC_VALID   0x01
-#define KVM_S390_PGM_FLAGS_ILC_0       0x02
-#define KVM_S390_PGM_FLAGS_ILC_1       0x04
-#define KVM_S390_PGM_FLAGS_ILC_MASK    0x06
-#define KVM_S390_PGM_FLAGS_NO_REWIND   0x08
-       __u8 flags;
-       __u8 pad[2];
-};
-
-struct kvm_s390_prefix_info {
-       __u32 address;
-};
-
-struct kvm_s390_extcall_info {
-       __u16 code;
-};
-
-struct kvm_s390_emerg_info {
-       __u16 code;
-};
-
-#define KVM_S390_STOP_FLAG_STORE_STATUS        0x01
-struct kvm_s390_stop_info {
-       __u32 flags;
-};
-
-struct kvm_s390_mchk_info {
-       __u64 cr14;
-       __u64 mcic;
-       __u64 failing_storage_address;
-       __u32 ext_damage_code;
-       __u32 pad;
-       __u8 fixed_logout[16];
-};
-
-struct kvm_s390_irq {
-       __u64 type;
-       union {
-               struct kvm_s390_io_info io;
-               struct kvm_s390_ext_info ext;
-               struct kvm_s390_pgm_info pgm;
-               struct kvm_s390_emerg_info emerg;
-               struct kvm_s390_extcall_info extcall;
-               struct kvm_s390_prefix_info prefix;
-               struct kvm_s390_stop_info stop;
-               struct kvm_s390_mchk_info mchk;
-               char reserved[64];
-       } u;
-};
-
-struct kvm_s390_irq_state {
-       __u64 buf;
-       __u32 flags;        /* will stay unused for compatibility reasons */
-       __u32 len;
-       __u32 reserved[4];  /* will stay unused for compatibility reasons */
-};
-
 /* for KVM_SET_GUEST_DEBUG */
 
 #define KVM_GUESTDBG_ENABLE            0x00000001
@@ -810,50 +618,6 @@ struct kvm_enable_cap {
        __u8  pad[64];
 };
 
-/* for KVM_PPC_GET_PVINFO */
-
-#define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
-
-struct kvm_ppc_pvinfo {
-       /* out */
-       __u32 flags;
-       __u32 hcall[4];
-       __u8  pad[108];
-};
-
-/* for KVM_PPC_GET_SMMU_INFO */
-#define KVM_PPC_PAGE_SIZES_MAX_SZ      8
-
-struct kvm_ppc_one_page_size {
-       __u32 page_shift;       /* Page shift (or 0) */
-       __u32 pte_enc;          /* Encoding in the HPTE (>>12) */
-};
-
-struct kvm_ppc_one_seg_page_size {
-       __u32 page_shift;       /* Base page shift of segment (or 0) */
-       __u32 slb_enc;          /* SLB encoding for BookS */
-       struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ];
-};
-
-#define KVM_PPC_PAGE_SIZES_REAL                0x00000001
-#define KVM_PPC_1T_SEGMENTS            0x00000002
-#define KVM_PPC_NO_HASH                        0x00000004
-
-struct kvm_ppc_smmu_info {
-       __u64 flags;
-       __u32 slb_size;
-       __u16 data_keys;        /* # storage keys supported for data */
-       __u16 instr_keys;       /* # storage keys supported for instructions */
-       struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
-};
-
-/* for KVM_PPC_RESIZE_HPT_{PREPARE,COMMIT} */
-struct kvm_ppc_resize_hpt {
-       __u64 flags;
-       __u32 shift;
-       __u32 pad;
-};
-
 #define KVMIO 0xAE
 
 /* machine type bits, to be used as argument to KVM_CREATE_VM */
@@ -923,9 +687,7 @@ struct kvm_ppc_resize_hpt {
 /* Bug in KVM_SET_USER_MEMORY_REGION fixed: */
 #define KVM_CAP_DESTROY_MEMORY_REGION_WORKS 21
 #define KVM_CAP_USER_NMI 22
-#ifdef __KVM_HAVE_GUEST_DEBUG
 #define KVM_CAP_SET_GUEST_DEBUG 23
-#endif
 #ifdef __KVM_HAVE_PIT
 #define KVM_CAP_REINJECT_CONTROL 24
 #endif
@@ -1156,8 +918,6 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_GUEST_MEMFD 234
 #define KVM_CAP_VM_TYPES 235
 
-#ifdef KVM_CAP_IRQ_ROUTING
-
 struct kvm_irq_routing_irqchip {
        __u32 irqchip;
        __u32 pin;
@@ -1222,42 +982,6 @@ struct kvm_irq_routing {
        struct kvm_irq_routing_entry entries[];
 };
 
-#endif
-
-#ifdef KVM_CAP_MCE
-/* x86 MCE */
-struct kvm_x86_mce {
-       __u64 status;
-       __u64 addr;
-       __u64 misc;
-       __u64 mcg_status;
-       __u8 bank;
-       __u8 pad1[7];
-       __u64 pad2[3];
-};
-#endif
-
-#ifdef KVM_CAP_XEN_HVM
-#define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR       (1 << 0)
-#define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL     (1 << 1)
-#define KVM_XEN_HVM_CONFIG_SHARED_INFO         (1 << 2)
-#define KVM_XEN_HVM_CONFIG_RUNSTATE            (1 << 3)
-#define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL       (1 << 4)
-#define KVM_XEN_HVM_CONFIG_EVTCHN_SEND         (1 << 5)
-#define KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG        (1 << 6)
-#define KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE        (1 << 7)
-
-struct kvm_xen_hvm_config {
-       __u32 flags;
-       __u32 msr;
-       __u64 blob_addr_32;
-       __u64 blob_addr_64;
-       __u8 blob_size_32;
-       __u8 blob_size_64;
-       __u8 pad2[30];
-};
-#endif
-
 #define KVM_IRQFD_FLAG_DEASSIGN (1 << 0)
 /*
  * Available with KVM_CAP_IRQFD_RESAMPLE
@@ -1442,11 +1166,6 @@ struct kvm_vfio_spapr_tce {
                                         struct kvm_userspace_memory_region2)
 
 /* enable ucontrol for s390 */
-struct kvm_s390_ucas_mapping {
-       __u64 user_addr;
-       __u64 vcpu_addr;
-       __u64 length;
-};
 #define KVM_S390_UCAS_MAP        _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping)
 #define KVM_S390_UCAS_UNMAP      _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping)
 #define KVM_S390_VCPU_FAULT     _IOW(KVMIO, 0x52, unsigned long)
@@ -1641,89 +1360,6 @@ struct kvm_enc_region {
 #define KVM_S390_NORMAL_RESET  _IO(KVMIO,   0xc3)
 #define KVM_S390_CLEAR_RESET   _IO(KVMIO,   0xc4)
 
-struct kvm_s390_pv_sec_parm {
-       __u64 origin;
-       __u64 length;
-};
-
-struct kvm_s390_pv_unp {
-       __u64 addr;
-       __u64 size;
-       __u64 tweak;
-};
-
-enum pv_cmd_dmp_id {
-       KVM_PV_DUMP_INIT,
-       KVM_PV_DUMP_CONFIG_STOR_STATE,
-       KVM_PV_DUMP_COMPLETE,
-       KVM_PV_DUMP_CPU,
-};
-
-struct kvm_s390_pv_dmp {
-       __u64 subcmd;
-       __u64 buff_addr;
-       __u64 buff_len;
-       __u64 gaddr;            /* For dump storage state */
-       __u64 reserved[4];
-};
-
-enum pv_cmd_info_id {
-       KVM_PV_INFO_VM,
-       KVM_PV_INFO_DUMP,
-};
-
-struct kvm_s390_pv_info_dump {
-       __u64 dump_cpu_buffer_len;
-       __u64 dump_config_mem_buffer_per_1m;
-       __u64 dump_config_finalize_len;
-};
-
-struct kvm_s390_pv_info_vm {
-       __u64 inst_calls_list[4];
-       __u64 max_cpus;
-       __u64 max_guests;
-       __u64 max_guest_addr;
-       __u64 feature_indication;
-};
-
-struct kvm_s390_pv_info_header {
-       __u32 id;
-       __u32 len_max;
-       __u32 len_written;
-       __u32 reserved;
-};
-
-struct kvm_s390_pv_info {
-       struct kvm_s390_pv_info_header header;
-       union {
-               struct kvm_s390_pv_info_dump dump;
-               struct kvm_s390_pv_info_vm vm;
-       };
-};
-
-enum pv_cmd_id {
-       KVM_PV_ENABLE,
-       KVM_PV_DISABLE,
-       KVM_PV_SET_SEC_PARMS,
-       KVM_PV_UNPACK,
-       KVM_PV_VERIFY,
-       KVM_PV_PREP_RESET,
-       KVM_PV_UNSHARE_ALL,
-       KVM_PV_INFO,
-       KVM_PV_DUMP,
-       KVM_PV_ASYNC_CLEANUP_PREPARE,
-       KVM_PV_ASYNC_CLEANUP_PERFORM,
-};
-
-struct kvm_pv_cmd {
-       __u32 cmd;      /* Command to be executed */
-       __u16 rc;       /* Ultravisor return code */
-       __u16 rrc;      /* Ultravisor return reason code */
-       __u64 data;     /* Data or address */
-       __u32 flags;    /* flags for future extensions. Must be 0 for now */
-       __u32 reserved[3];
-};
-
 /* Available with KVM_CAP_S390_PROTECTED */
 #define KVM_S390_PV_COMMAND            _IOWR(KVMIO, 0xc5, struct kvm_pv_cmd)
 
@@ -1737,58 +1373,6 @@ struct kvm_pv_cmd {
 #define KVM_XEN_HVM_GET_ATTR   _IOWR(KVMIO, 0xc8, struct kvm_xen_hvm_attr)
 #define KVM_XEN_HVM_SET_ATTR   _IOW(KVMIO,  0xc9, struct kvm_xen_hvm_attr)
 
-struct kvm_xen_hvm_attr {
-       __u16 type;
-       __u16 pad[3];
-       union {
-               __u8 long_mode;
-               __u8 vector;
-               __u8 runstate_update_flag;
-               struct {
-                       __u64 gfn;
-#define KVM_XEN_INVALID_GFN ((__u64)-1)
-               } shared_info;
-               struct {
-                       __u32 send_port;
-                       __u32 type; /* EVTCHNSTAT_ipi / EVTCHNSTAT_interdomain */
-                       __u32 flags;
-#define KVM_XEN_EVTCHN_DEASSIGN                (1 << 0)
-#define KVM_XEN_EVTCHN_UPDATE          (1 << 1)
-#define KVM_XEN_EVTCHN_RESET           (1 << 2)
-                       /*
-                        * Events sent by the guest are either looped back to
-                        * the guest itself (potentially on a different port#)
-                        * or signalled via an eventfd.
-                        */
-                       union {
-                               struct {
-                                       __u32 port;
-                                       __u32 vcpu;
-                                       __u32 priority;
-                               } port;
-                               struct {
-                                       __u32 port; /* Zero for eventfd */
-                                       __s32 fd;
-                               } eventfd;
-                               __u32 padding[4];
-                       } deliver;
-               } evtchn;
-               __u32 xen_version;
-               __u64 pad[8];
-       } u;
-};
-
-
-/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */
-#define KVM_XEN_ATTR_TYPE_LONG_MODE            0x0
-#define KVM_XEN_ATTR_TYPE_SHARED_INFO          0x1
-#define KVM_XEN_ATTR_TYPE_UPCALL_VECTOR                0x2
-/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */
-#define KVM_XEN_ATTR_TYPE_EVTCHN               0x3
-#define KVM_XEN_ATTR_TYPE_XEN_VERSION          0x4
-/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG */
-#define KVM_XEN_ATTR_TYPE_RUNSTATE_UPDATE_FLAG 0x5
-
 /* Per-vCPU Xen attributes */
 #define KVM_XEN_VCPU_GET_ATTR  _IOWR(KVMIO, 0xca, struct kvm_xen_vcpu_attr)
 #define KVM_XEN_VCPU_SET_ATTR  _IOW(KVMIO,  0xcb, struct kvm_xen_vcpu_attr)
@@ -1799,242 +1383,6 @@ struct kvm_xen_hvm_attr {
 #define KVM_GET_SREGS2             _IOR(KVMIO,  0xcc, struct kvm_sregs2)
 #define KVM_SET_SREGS2             _IOW(KVMIO,  0xcd, struct kvm_sregs2)
 
-struct kvm_xen_vcpu_attr {
-       __u16 type;
-       __u16 pad[3];
-       union {
-               __u64 gpa;
-#define KVM_XEN_INVALID_GPA ((__u64)-1)
-               __u64 pad[8];
-               struct {
-                       __u64 state;
-                       __u64 state_entry_time;
-                       __u64 time_running;
-                       __u64 time_runnable;
-                       __u64 time_blocked;
-                       __u64 time_offline;
-               } runstate;
-               __u32 vcpu_id;
-               struct {
-                       __u32 port;
-                       __u32 priority;
-                       __u64 expires_ns;
-               } timer;
-               __u8 vector;
-       } u;
-};
-
-/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */
-#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO       0x0
-#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO  0x1
-#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR   0x2
-#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT        0x3
-#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA   0x4
-#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 0x5
-/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */
-#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID         0x6
-#define KVM_XEN_VCPU_ATTR_TYPE_TIMER           0x7
-#define KVM_XEN_VCPU_ATTR_TYPE_UPCALL_VECTOR   0x8
-
-/* Secure Encrypted Virtualization command */
-enum sev_cmd_id {
-       /* Guest initialization commands */
-       KVM_SEV_INIT = 0,
-       KVM_SEV_ES_INIT,
-       /* Guest launch commands */
-       KVM_SEV_LAUNCH_START,
-       KVM_SEV_LAUNCH_UPDATE_DATA,
-       KVM_SEV_LAUNCH_UPDATE_VMSA,
-       KVM_SEV_LAUNCH_SECRET,
-       KVM_SEV_LAUNCH_MEASURE,
-       KVM_SEV_LAUNCH_FINISH,
-       /* Guest migration commands (outgoing) */
-       KVM_SEV_SEND_START,
-       KVM_SEV_SEND_UPDATE_DATA,
-       KVM_SEV_SEND_UPDATE_VMSA,
-       KVM_SEV_SEND_FINISH,
-       /* Guest migration commands (incoming) */
-       KVM_SEV_RECEIVE_START,
-       KVM_SEV_RECEIVE_UPDATE_DATA,
-       KVM_SEV_RECEIVE_UPDATE_VMSA,
-       KVM_SEV_RECEIVE_FINISH,
-       /* Guest status and debug commands */
-       KVM_SEV_GUEST_STATUS,
-       KVM_SEV_DBG_DECRYPT,
-       KVM_SEV_DBG_ENCRYPT,
-       /* Guest certificates commands */
-       KVM_SEV_CERT_EXPORT,
-       /* Attestation report */
-       KVM_SEV_GET_ATTESTATION_REPORT,
-       /* Guest Migration Extension */
-       KVM_SEV_SEND_CANCEL,
-
-       KVM_SEV_NR_MAX,
-};
-
-struct kvm_sev_cmd {
-       __u32 id;
-       __u64 data;
-       __u32 error;
-       __u32 sev_fd;
-};
-
-struct kvm_sev_launch_start {
-       __u32 handle;
-       __u32 policy;
-       __u64 dh_uaddr;
-       __u32 dh_len;
-       __u64 session_uaddr;
-       __u32 session_len;
-};
-
-struct kvm_sev_launch_update_data {
-       __u64 uaddr;
-       __u32 len;
-};
-
-
-struct kvm_sev_launch_secret {
-       __u64 hdr_uaddr;
-       __u32 hdr_len;
-       __u64 guest_uaddr;
-       __u32 guest_len;
-       __u64 trans_uaddr;
-       __u32 trans_len;
-};
-
-struct kvm_sev_launch_measure {
-       __u64 uaddr;
-       __u32 len;
-};
-
-struct kvm_sev_guest_status {
-       __u32 handle;
-       __u32 policy;
-       __u32 state;
-};
-
-struct kvm_sev_dbg {
-       __u64 src_uaddr;
-       __u64 dst_uaddr;
-       __u32 len;
-};
-
-struct kvm_sev_attestation_report {
-       __u8 mnonce[16];
-       __u64 uaddr;
-       __u32 len;
-};
-
-struct kvm_sev_send_start {
-       __u32 policy;
-       __u64 pdh_cert_uaddr;
-       __u32 pdh_cert_len;
-       __u64 plat_certs_uaddr;
-       __u32 plat_certs_len;
-       __u64 amd_certs_uaddr;
-       __u32 amd_certs_len;
-       __u64 session_uaddr;
-       __u32 session_len;
-};
-
-struct kvm_sev_send_update_data {
-       __u64 hdr_uaddr;
-       __u32 hdr_len;
-       __u64 guest_uaddr;
-       __u32 guest_len;
-       __u64 trans_uaddr;
-       __u32 trans_len;
-};
-
-struct kvm_sev_receive_start {
-       __u32 handle;
-       __u32 policy;
-       __u64 pdh_uaddr;
-       __u32 pdh_len;
-       __u64 session_uaddr;
-       __u32 session_len;
-};
-
-struct kvm_sev_receive_update_data {
-       __u64 hdr_uaddr;
-       __u32 hdr_len;
-       __u64 guest_uaddr;
-       __u32 guest_len;
-       __u64 trans_uaddr;
-       __u32 trans_len;
-};
-
-#define KVM_DEV_ASSIGN_ENABLE_IOMMU    (1 << 0)
-#define KVM_DEV_ASSIGN_PCI_2_3         (1 << 1)
-#define KVM_DEV_ASSIGN_MASK_INTX       (1 << 2)
-
-struct kvm_assigned_pci_dev {
-       __u32 assigned_dev_id;
-       __u32 busnr;
-       __u32 devfn;
-       __u32 flags;
-       __u32 segnr;
-       union {
-               __u32 reserved[11];
-       };
-};
-
-#define KVM_DEV_IRQ_HOST_INTX    (1 << 0)
-#define KVM_DEV_IRQ_HOST_MSI     (1 << 1)
-#define KVM_DEV_IRQ_HOST_MSIX    (1 << 2)
-
-#define KVM_DEV_IRQ_GUEST_INTX   (1 << 8)
-#define KVM_DEV_IRQ_GUEST_MSI    (1 << 9)
-#define KVM_DEV_IRQ_GUEST_MSIX   (1 << 10)
-
-#define KVM_DEV_IRQ_HOST_MASK   0x00ff
-#define KVM_DEV_IRQ_GUEST_MASK   0xff00
-
-struct kvm_assigned_irq {
-       __u32 assigned_dev_id;
-       __u32 host_irq; /* ignored (legacy field) */
-       __u32 guest_irq;
-       __u32 flags;
-       union {
-               __u32 reserved[12];
-       };
-};
-
-struct kvm_assigned_msix_nr {
-       __u32 assigned_dev_id;
-       __u16 entry_nr;
-       __u16 padding;
-};
-
-#define KVM_MAX_MSIX_PER_DEV           256
-struct kvm_assigned_msix_entry {
-       __u32 assigned_dev_id;
-       __u32 gsi;
-       __u16 entry; /* The index of entry in the MSI-X table */
-       __u16 padding[3];
-};
-
-#define KVM_X2APIC_API_USE_32BIT_IDS            (1ULL << 0)
-#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK  (1ULL << 1)
-
-/* Available with KVM_CAP_ARM_USER_IRQ */
-
-/* Bits for run->s.regs.device_irq_level */
-#define KVM_ARM_DEV_EL1_VTIMER         (1 << 0)
-#define KVM_ARM_DEV_EL1_PTIMER         (1 << 1)
-#define KVM_ARM_DEV_PMU                        (1 << 2)
-
-struct kvm_hyperv_eventfd {
-       __u32 conn_id;
-       __s32 fd;
-       __u32 flags;
-       __u32 padding[3];
-};
-
-#define KVM_HYPERV_CONN_ID_MASK                0x00ffffff
-#define KVM_HYPERV_EVENTFD_DEASSIGN    (1 << 0)
-
 #define KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE    (1 << 0)
 #define KVM_DIRTY_LOG_INITIALLY_SET            (1 << 1)
 
@@ -2180,33 +1528,6 @@ struct kvm_stats_desc {
 /* Available with KVM_CAP_S390_ZPCI_OP */
 #define KVM_S390_ZPCI_OP         _IOW(KVMIO,  0xd1, struct kvm_s390_zpci_op)
 
-struct kvm_s390_zpci_op {
-       /* in */
-       __u32 fh;               /* target device */
-       __u8  op;               /* operation to perform */
-       __u8  pad[3];
-       union {
-               /* for KVM_S390_ZPCIOP_REG_AEN */
-               struct {
-                       __u64 ibv;      /* Guest addr of interrupt bit vector */
-                       __u64 sb;       /* Guest addr of summary bit */
-                       __u32 flags;
-                       __u32 noi;      /* Number of interrupts */
-                       __u8 isc;       /* Guest interrupt subclass */
-                       __u8 sbo;       /* Offset of guest summary bit vector */
-                       __u16 pad;
-               } reg_aen;
-               __u64 reserved[8];
-       } u;
-};
-
-/* types for kvm_s390_zpci_op->op */
-#define KVM_S390_ZPCIOP_REG_AEN                0
-#define KVM_S390_ZPCIOP_DEREG_AEN      1
-
-/* flags for kvm_s390_zpci_op->u.reg_aen.flags */
-#define KVM_S390_ZPCIOP_REGAEN_HOST    (1 << 0)
-
 /* Available with KVM_CAP_MEMORY_ATTRIBUTES */
 #define KVM_SET_MEMORY_ATTRIBUTES              _IOW(KVMIO,  0xd2, struct kvm_memory_attributes)
 
index d5b9cfbd9ceac69323d0fe487cc49ab388a2e523..628d46a0da92eb0393dd592a38e987d08dcf6db0 100644 (file)
@@ -142,7 +142,7 @@ struct snd_hwdep_dsp_image {
  *                                                                           *
  *****************************************************************************/
 
-#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 16)
+#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 17)
 
 typedef unsigned long snd_pcm_uframes_t;
 typedef signed long snd_pcm_sframes_t;
@@ -416,7 +416,7 @@ struct snd_pcm_hw_params {
        unsigned int rmask;             /* W: requested masks */
        unsigned int cmask;             /* R: changed masks */
        unsigned int info;              /* R: Info flags for returned setup */
-       unsigned int msbits;            /* R: used most significant bits */
+       unsigned int msbits;            /* R: used most significant bits (in sample bit-width) */
        unsigned int rate_num;          /* R: rate numerator */
        unsigned int rate_den;          /* R: rate denominator */
        snd_pcm_uframes_t fifo_size;    /* R: chip FIFO size in frames */
index 5fa7957f6e0f56646249c278b7434f300754df77..25810e18b0a73272f42ff3a8d9335ee79699b6a0 100644 (file)
@@ -182,6 +182,7 @@ class NlMsg:
             self.done = 1
             extack_off = 20
         elif self.nl_type == Netlink.NLMSG_DONE:
+            self.error = struct.unpack("i", self.raw[0:4])[0]
             self.done = 1
             extack_off = 4
 
index 4a41856938a8889403278a4ad44c599d835b887a..1b29030021eeba71e34eeb8adcf69278f11a1dda 100644 (file)
@@ -41,7 +41,7 @@ static char *_get_cpuid(void)
        char *mimpid = NULL;
        char *cpuid = NULL;
        int read;
-       unsigned long line_sz;
+       size_t line_sz;
        FILE *cpuinfo;
 
        cpuinfo = fopen(CPUINFO, "r");
index ec5e21932876038b99afbfa30560d856efd8afd5..4790c735599bdd97b62a39edd861230464abc5d8 100644 (file)
@@ -970,7 +970,7 @@ int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
        if (dso->annotate_warned)
                return -1;
 
-       if (not_annotated) {
+       if (not_annotated || !sym->annotate2) {
                err = symbol__annotate2(ms, evsel, &browser.arch);
                if (err) {
                        char msg[BUFSIZ];
index ac002d907d81801c941876731e29acfc8dcf97b3..50ca92255ff62a61e2923179c1e7f4fb7e98ded5 100644 (file)
@@ -2461,6 +2461,9 @@ int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
        if (parch)
                *parch = arch;
 
+       if (!list_empty(&notes->src->source))
+               return 0;
+
        args.arch = arch;
        args.ms = *ms;
        if (annotate_opts.full_addr)
index fb54bd38e7d0947cd1e1acef59977d46b0082028..d931a898c434be0d430759db9e2c8572dcdb65b5 100644 (file)
@@ -284,6 +284,7 @@ static inline __u32 check_lock_type(__u64 lock, __u32 flags)
        struct task_struct *curr;
        struct mm_struct___old *mm_old;
        struct mm_struct___new *mm_new;
+       struct sighand_struct *sighand;
 
        switch (flags) {
        case LCB_F_READ:  /* rwsem */
@@ -305,7 +306,9 @@ static inline __u32 check_lock_type(__u64 lock, __u32 flags)
                break;
        case LCB_F_SPIN:  /* spinlock */
                curr = bpf_get_current_task_btf();
-               if (&curr->sighand->siglock == (void *)lock)
+               sighand = curr->sighand;
+
+               if (sighand && &sighand->siglock == (void *)lock)
                        return LCD_F_SIGHAND_LOCK;
                break;
        default:
index 61c69297e7978fceed700be3ad43a7a870d20de2..3482248aa34424e1d690ecea1faef822d152edd3 100644 (file)
@@ -1001,6 +1001,7 @@ static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port)
        struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
        struct cxl_dev_state *cxlds = cxlmd->cxlds;
        struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
+       struct access_coordinate ep_c[ACCESS_COORDINATE_MAX];
        struct range pmem_range = {
                .start = cxlds->pmem_res.start,
                .end = cxlds->pmem_res.end,
@@ -1020,6 +1021,12 @@ static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port)
                dpa_perf_setup(port, &pmem_range, &mds->pmem_perf);
 
        cxl_memdev_update_perf(cxlmd);
+
+       /*
+        * This function is here to only test the topology iterator. It serves
+        * no other purpose.
+        */
+       cxl_endpoint_get_perf_coordinates(port, ep_c);
 }
 
 static struct cxl_mock_ops cxl_mock_ops = {
index 39ad96a18123f626c311aaa2fdf8213594b7d67d..edcd26106557b478eea1527077ffde97347c9012 100644 (file)
@@ -205,6 +205,9 @@ __weak noinline struct file *bpf_testmod_return_ptr(int arg)
        case 5: return (void *)~(1ull << 30);   /* trigger extable */
        case 6: return &f;                      /* valid addr */
        case 7: return (void *)((long)&f | 1);  /* kernel tricks */
+#ifdef CONFIG_X86_64
+       case 8: return (void *)VSYSCALL_ADDR;   /* vsyscall page address */
+#endif
        default: return NULL;
        }
 }
index b1ede624986676a554514105936698fdd2b0a915..b7c8f29c09a978895c1176e1a39aeda8c97e8416 100644 (file)
@@ -18,7 +18,7 @@ echo 'sched:*' > set_event
 
 yield
 
-count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
+count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
 if [ $count -lt 3 ]; then
     fail "at least fork, exec and exit events should be recorded"
 fi
@@ -29,7 +29,7 @@ echo 1 > events/sched/enable
 
 yield
 
-count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
+count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
 if [ $count -lt 3 ]; then
     fail "at least fork, exec and exit events should be recorded"
 fi
@@ -40,7 +40,7 @@ echo 0 > events/sched/enable
 
 yield
 
-count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
+count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
 if [ $count -ne 0 ]; then
     fail "any of scheduler events should not be recorded"
 fi
index 110d73917615d177d5d7a891f08d523619c404f3..02a2a1b267c1eae76f24011c64f9a0759d55032f 100644 (file)
@@ -1,3 +1,5 @@
 CONFIG_IOMMUFD=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
 CONFIG_FAULT_INJECTION=y
 CONFIG_IOMMUFD_TEST=y
+CONFIG_FAILSLAB=y
index 7b89362da4bfd384efe49681451c276ecd78ee16..14bbab0cce13521abbcae9bbd3772a567239c77f 100644 (file)
@@ -292,15 +292,17 @@ void ksft_test_result_code(int exit_code, const char *test_name,
        }
 
        /* Docs seem to call for double space if directive is absent */
-       if (!directive[0] && msg[0])
+       if (!directive[0] && msg)
                directive = " #  ";
 
-       va_start(args, msg);
        printf("%s %u %s%s", tap_code, ksft_test_num(), test_name, directive);
        errno = saved_errno;
-       vprintf(msg, args);
+       if (msg) {
+               va_start(args, msg);
+               vprintf(msg, args);
+               va_end(args);
+       }
        printf("\n");
-       va_end(args);
 }
 
 static inline __noreturn int ksft_exit_pass(void)
index 4fd735e48ee7eea99702fcb3e27f539c887b15bc..d98702b6955df24e72366f2246ad5b3da7951b5a 100644 (file)
@@ -56,7 +56,6 @@
 #include <asm/types.h>
 #include <ctype.h>
 #include <errno.h>
-#include <limits.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
                FIXTURE_DATA(fixture_name) self; \
                pid_t child = 1; \
                int status = 0; \
+               bool jmp = false; \
                memset(&self, 0, sizeof(FIXTURE_DATA(fixture_name))); \
                if (setjmp(_metadata->env) == 0) { \
                        /* Use the same _metadata. */ \
                                _metadata->exit_code = KSFT_FAIL; \
                        } \
                } \
+               else \
+                       jmp = true; \
                if (child == 0) { \
-                       if (_metadata->setup_completed && !_metadata->teardown_parent) \
+                       if (_metadata->setup_completed && !_metadata->teardown_parent && !jmp) \
                                fixture_name##_teardown(_metadata, &self, variant->data); \
                        _exit(0); \
                } \
@@ -1156,7 +1158,7 @@ void __run_test(struct __fixture_metadata *f,
                struct __test_metadata *t)
 {
        struct __test_xfail *xfail;
-       char test_name[LINE_MAX];
+       char *test_name;
        const char *diagnostic;
 
        /* reset test struct */
@@ -1164,8 +1166,12 @@ void __run_test(struct __fixture_metadata *f,
        t->trigger = 0;
        memset(t->results->reason, 0, sizeof(t->results->reason));
 
-       snprintf(test_name, sizeof(test_name), "%s%s%s.%s",
-                f->name, variant->name[0] ? "." : "", variant->name, t->name);
+       if (asprintf(&test_name, "%s%s%s.%s", f->name,
+               variant->name[0] ? "." : "", variant->name, t->name) == -1) {
+               ksft_print_msg("ERROR ALLOCATING MEMORY\n");
+               t->exit_code = KSFT_FAIL;
+               _exit(t->exit_code);
+       }
 
        ksft_print_msg(" RUN           %s ...\n", test_name);
 
@@ -1202,7 +1208,8 @@ void __run_test(struct __fixture_metadata *f,
                diagnostic = "unknown";
 
        ksft_test_result_code(t->exit_code, test_name,
-                             diagnostic ? "%s" : "", diagnostic);
+                             diagnostic ? "%s" : NULL, diagnostic);
+       free(test_name);
 }
 
 static int test_harness_run(int argc, char **argv)
index eef816b80993f528569f0de79b5f5e5fcda0e289..ca917c71ff602da5ab0805c4cee51e0df5d185e5 100644 (file)
@@ -84,6 +84,18 @@ static struct vm_gic vm_gic_create_with_vcpus(uint32_t gic_dev_type,
        return v;
 }
 
+static struct vm_gic vm_gic_create_barebones(uint32_t gic_dev_type)
+{
+       struct vm_gic v;
+
+       v.gic_dev_type = gic_dev_type;
+       v.vm = vm_create_barebones();
+       v.gic_fd = kvm_create_device(v.vm, gic_dev_type);
+
+       return v;
+}
+
+
 static void vm_gic_destroy(struct vm_gic *v)
 {
        close(v->gic_fd);
@@ -357,6 +369,40 @@ static void test_vcpus_then_vgic(uint32_t gic_dev_type)
        vm_gic_destroy(&v);
 }
 
+#define KVM_VGIC_V2_ATTR(offset, cpu) \
+       (FIELD_PREP(KVM_DEV_ARM_VGIC_OFFSET_MASK, offset) | \
+        FIELD_PREP(KVM_DEV_ARM_VGIC_CPUID_MASK, cpu))
+
+#define GIC_CPU_CTRL   0x00
+
+static void test_v2_uaccess_cpuif_no_vcpus(void)
+{
+       struct vm_gic v;
+       u64 val = 0;
+       int ret;
+
+       v = vm_gic_create_barebones(KVM_DEV_TYPE_ARM_VGIC_V2);
+       subtest_dist_rdist(&v);
+
+       ret = __kvm_has_device_attr(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
+                                   KVM_VGIC_V2_ATTR(GIC_CPU_CTRL, 0));
+       TEST_ASSERT(ret && errno == EINVAL,
+                   "accessed non-existent CPU interface, want errno: %i",
+                   EINVAL);
+       ret = __kvm_device_attr_get(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
+                                   KVM_VGIC_V2_ATTR(GIC_CPU_CTRL, 0), &val);
+       TEST_ASSERT(ret && errno == EINVAL,
+                   "accessed non-existent CPU interface, want errno: %i",
+                   EINVAL);
+       ret = __kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
+                                   KVM_VGIC_V2_ATTR(GIC_CPU_CTRL, 0), &val);
+       TEST_ASSERT(ret && errno == EINVAL,
+                   "accessed non-existent CPU interface, want errno: %i",
+                   EINVAL);
+
+       vm_gic_destroy(&v);
+}
+
 static void test_v3_new_redist_regions(void)
 {
        struct kvm_vcpu *vcpus[NR_VCPUS];
@@ -675,6 +721,9 @@ void run_tests(uint32_t gic_dev_type)
        test_vcpus_then_vgic(gic_dev_type);
        test_vgic_then_vcpus(gic_dev_type);
 
+       if (VGIC_DEV_IS_V2(gic_dev_type))
+               test_v2_uaccess_cpuif_no_vcpus();
+
        if (VGIC_DEV_IS_V3(gic_dev_type)) {
                test_v3_new_redist_regions();
                test_v3_typer_accesses();
index 6628dc4dda89f3c12cefa7a459aed11687b91799..1a6da7389bf1f5b2d24295e6aed85ced77506349 100644 (file)
@@ -22,10 +22,11 @@ static void guest_code(uint64_t start_gpa, uint64_t end_gpa, uint64_t stride)
 {
        uint64_t gpa;
 
-       for (gpa = start_gpa; gpa < end_gpa; gpa += stride)
-               *((volatile uint64_t *)gpa) = gpa;
-
-       GUEST_DONE();
+       for (;;) {
+               for (gpa = start_gpa; gpa < end_gpa; gpa += stride)
+                       *((volatile uint64_t *)gpa) = gpa;
+               GUEST_SYNC(0);
+       }
 }
 
 struct vcpu_info {
@@ -55,7 +56,7 @@ static void rendezvous_with_boss(void)
 static void run_vcpu(struct kvm_vcpu *vcpu)
 {
        vcpu_run(vcpu);
-       TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_DONE);
+       TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_SYNC);
 }
 
 static void *vcpu_worker(void *data)
@@ -64,17 +65,13 @@ static void *vcpu_worker(void *data)
        struct kvm_vcpu *vcpu = info->vcpu;
        struct kvm_vm *vm = vcpu->vm;
        struct kvm_sregs sregs;
-       struct kvm_regs regs;
 
        vcpu_args_set(vcpu, 3, info->start_gpa, info->end_gpa, vm->page_size);
 
-       /* Snapshot regs before the first run. */
-       vcpu_regs_get(vcpu, &regs);
        rendezvous_with_boss();
 
        run_vcpu(vcpu);
        rendezvous_with_boss();
-       vcpu_regs_set(vcpu, &regs);
        vcpu_sregs_get(vcpu, &sregs);
 #ifdef __x86_64__
        /* Toggle CR0.WP to trigger a MMU context reset. */
index 06b43ed23580b67c060aeaadea11b06641a629c3..bd57d991e27d85acca0cd570981e240ed9f45e87 100644 (file)
@@ -333,7 +333,7 @@ static void test_invalid_memory_region_flags(void)
        struct kvm_vm *vm;
        int r, i;
 
-#if defined __aarch64__ || defined __x86_64__
+#if defined __aarch64__ || defined __riscv || defined __x86_64__
        supported_flags |= KVM_MEM_READONLY;
 #endif
 
index 29609b52f8fa0c58bfb38207ef29bf6283f43932..26c85815f7e983a33c025aa1daab6daa45c0f91b 100644 (file)
@@ -416,12 +416,30 @@ static void guest_rd_wr_counters(uint32_t base_msr, uint8_t nr_possible_counters
 
 static void guest_test_gp_counters(void)
 {
+       uint8_t pmu_version = guest_get_pmu_version();
        uint8_t nr_gp_counters = 0;
        uint32_t base_msr;
 
-       if (guest_get_pmu_version())
+       if (pmu_version)
                nr_gp_counters = this_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);
 
+       /*
+        * For v2+ PMUs, PERF_GLOBAL_CTRL's architectural post-RESET value is
+        * "Sets bits n-1:0 and clears the upper bits", where 'n' is the number
+        * of GP counters.  If there are no GP counters, require KVM to leave
+        * PERF_GLOBAL_CTRL '0'.  This edge case isn't covered by the SDM, but
+        * follow the spirit of the architecture and only globally enable GP
+        * counters, of which there are none.
+        */
+       if (pmu_version > 1) {
+               uint64_t global_ctrl = rdmsr(MSR_CORE_PERF_GLOBAL_CTRL);
+
+               if (nr_gp_counters)
+                       GUEST_ASSERT_EQ(global_ctrl, GENMASK_ULL(nr_gp_counters - 1, 0));
+               else
+                       GUEST_ASSERT_EQ(global_ctrl, 0);
+       }
+
        if (this_cpu_has(X86_FEATURE_PDCM) &&
            rdmsr(MSR_IA32_PERF_CAPABILITIES) & PMU_CAP_FW_WRITES)
                base_msr = MSR_IA32_PMC0;
index 7f6f5f23fb9b67fcb186a0e9c9ad00aaced6d2d3..977948fd52e6b8cf7e71dfa84874d5e8af7d9c09 100644 (file)
 #define NESTED_TEST_MEM1               0xc0001000
 #define NESTED_TEST_MEM2               0xc0002000
 
-static void l2_guest_code(void)
+static void l2_guest_code(u64 *a, u64 *b)
 {
-       *(volatile uint64_t *)NESTED_TEST_MEM1;
-       *(volatile uint64_t *)NESTED_TEST_MEM1 = 1;
+       READ_ONCE(*a);
+       WRITE_ONCE(*a, 1);
        GUEST_SYNC(true);
        GUEST_SYNC(false);
 
-       *(volatile uint64_t *)NESTED_TEST_MEM2 = 1;
+       WRITE_ONCE(*b, 1);
        GUEST_SYNC(true);
-       *(volatile uint64_t *)NESTED_TEST_MEM2 = 1;
+       WRITE_ONCE(*b, 1);
        GUEST_SYNC(true);
        GUEST_SYNC(false);
 
@@ -45,17 +45,33 @@ static void l2_guest_code(void)
        vmcall();
 }
 
+static void l2_guest_code_ept_enabled(void)
+{
+       l2_guest_code((u64 *)NESTED_TEST_MEM1, (u64 *)NESTED_TEST_MEM2);
+}
+
+static void l2_guest_code_ept_disabled(void)
+{
+       /* Access the same L1 GPAs as l2_guest_code_ept_enabled() */
+       l2_guest_code((u64 *)GUEST_TEST_MEM, (u64 *)GUEST_TEST_MEM);
+}
+
 void l1_guest_code(struct vmx_pages *vmx)
 {
 #define L2_GUEST_STACK_SIZE 64
        unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
+       void *l2_rip;
 
        GUEST_ASSERT(vmx->vmcs_gpa);
        GUEST_ASSERT(prepare_for_vmx_operation(vmx));
        GUEST_ASSERT(load_vmcs(vmx));
 
-       prepare_vmcs(vmx, l2_guest_code,
-                    &l2_guest_stack[L2_GUEST_STACK_SIZE]);
+       if (vmx->eptp_gpa)
+               l2_rip = l2_guest_code_ept_enabled;
+       else
+               l2_rip = l2_guest_code_ept_disabled;
+
+       prepare_vmcs(vmx, l2_rip, &l2_guest_stack[L2_GUEST_STACK_SIZE]);
 
        GUEST_SYNC(false);
        GUEST_ASSERT(!vmlaunch());
@@ -64,7 +80,7 @@ void l1_guest_code(struct vmx_pages *vmx)
        GUEST_DONE();
 }
 
-int main(int argc, char *argv[])
+static void test_vmx_dirty_log(bool enable_ept)
 {
        vm_vaddr_t vmx_pages_gva = 0;
        struct vmx_pages *vmx;
@@ -76,8 +92,7 @@ int main(int argc, char *argv[])
        struct ucall uc;
        bool done = false;
 
-       TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
-       TEST_REQUIRE(kvm_cpu_has_ept());
+       pr_info("Nested EPT: %s\n", enable_ept ? "enabled" : "disabled");
 
        /* Create VM */
        vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code);
@@ -103,11 +118,16 @@ int main(int argc, char *argv[])
         *
         * Note that prepare_eptp should be called only L1's GPA map is done,
         * meaning after the last call to virt_map.
+        *
+        * When EPT is disabled, the L2 guest code will still access the same L1
+        * GPAs as the EPT enabled case.
         */
-       prepare_eptp(vmx, vm, 0);
-       nested_map_memslot(vmx, vm, 0);
-       nested_map(vmx, vm, NESTED_TEST_MEM1, GUEST_TEST_MEM, 4096);
-       nested_map(vmx, vm, NESTED_TEST_MEM2, GUEST_TEST_MEM, 4096);
+       if (enable_ept) {
+               prepare_eptp(vmx, vm, 0);
+               nested_map_memslot(vmx, vm, 0);
+               nested_map(vmx, vm, NESTED_TEST_MEM1, GUEST_TEST_MEM, 4096);
+               nested_map(vmx, vm, NESTED_TEST_MEM2, GUEST_TEST_MEM, 4096);
+       }
 
        bmap = bitmap_zalloc(TEST_MEM_PAGES);
        host_test_mem = addr_gpa2hva(vm, GUEST_TEST_MEM);
@@ -148,3 +168,15 @@ int main(int argc, char *argv[])
                }
        }
 }
+
+int main(int argc, char *argv[])
+{
+       TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
+
+       test_vmx_dirty_log(/*enable_ept=*/false);
+
+       if (kvm_cpu_has_ept())
+               test_vmx_dirty_log(/*enable_ept=*/true);
+
+       return 0;
+}
index 200bedcdc32e9cf0fd834ad39bd0cab435743987..1e01d3ddc11c58ffb5af9c8733c93ec17297fed6 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/mman.h>
 #include <linux/prctl.h>
 
+#define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/auxv.h>
index 374a308174d2ba7c17f496a4c94364e34815e355..48dc151f8fca8ab8a1ef300860cb59e0f491a2a8 100644 (file)
@@ -54,7 +54,6 @@ int test_nr;
 u64 shadow_pkey_reg;
 int dprint_in_signal;
 char dprint_in_signal_buffer[DPRINT_IN_SIGNAL_BUF_SIZE];
-char buf[256];
 
 void cat_into_file(char *str, char *file)
 {
@@ -1745,42 +1744,6 @@ void pkey_setup_shadow(void)
        shadow_pkey_reg = __read_pkey_reg();
 }
 
-pid_t parent_pid;
-
-void restore_settings_atexit(void)
-{
-       if (parent_pid == getpid())
-               cat_into_file(buf, "/proc/sys/vm/nr_hugepages");
-}
-
-void save_settings(void)
-{
-       int fd;
-       int err;
-
-       if (geteuid())
-               return;
-
-       fd = open("/proc/sys/vm/nr_hugepages", O_RDONLY);
-       if (fd < 0) {
-               fprintf(stderr, "error opening\n");
-               perror("error: ");
-               exit(__LINE__);
-       }
-
-       /* -1 to guarantee leaving the trailing \0 */
-       err = read(fd, buf, sizeof(buf)-1);
-       if (err < 0) {
-               fprintf(stderr, "error reading\n");
-               perror("error: ");
-               exit(__LINE__);
-       }
-
-       parent_pid = getpid();
-       atexit(restore_settings_atexit);
-       close(fd);
-}
-
 int main(void)
 {
        int nr_iterations = 22;
@@ -1788,7 +1751,6 @@ int main(void)
 
        srand((unsigned int)time(NULL));
 
-       save_settings();
        setup_handlers();
 
        printf("has pkeys: %d\n", pkeys_supported);
index c2c542fe7b17bb6a8b8b59b4a4de79ba26a07043..4bdb3a0c7a606e4201e445002eb6795390d8b374 100755 (executable)
@@ -385,6 +385,7 @@ CATEGORY="ksm_numa" run_test ./ksm_tests -N -m 0
 CATEGORY="ksm" run_test ./ksm_functional_tests
 
 # protection_keys tests
+nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages)
 if [ -x ./protection_keys_32 ]
 then
        CATEGORY="pkey" run_test ./protection_keys_32
@@ -394,6 +395,7 @@ if [ -x ./protection_keys_64 ]
 then
        CATEGORY="pkey" run_test ./protection_keys_64
 fi
+echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages
 
 if [ -x ./soft-dirty ]
 then
index 6c988bd2f335677b9b87af1594407e63f907e542..d3c7f5fb3e7b778dc5e0e36eb71da09372f9acef 100644 (file)
@@ -300,7 +300,7 @@ int create_pagecache_thp_and_fd(const char *testfile, size_t fd_size, int *fd,
                char **addr)
 {
        size_t i;
-       int dummy;
+       int __attribute__((unused)) dummy = 0;
 
        srand(time(NULL));
 
index 2fb6dd8adba6945d0000c19fe90da1002d8c0dd4..8b984fa042869e595507368541504f0b04d42014 100644 (file)
@@ -86,7 +86,7 @@ static void netstat_read_type(FILE *fnetstat, struct netstat **dest, char *line)
 
        pos = strchr(line, ' ') + 1;
 
-       if (fscanf(fnetstat, type->header_name) == EOF)
+       if (fscanf(fnetstat, "%[^ :]", type->header_name) == EOF)
                test_error("fscanf(%s)", type->header_name);
        if (fread(&tmp, 1, 1, fnetstat) != 1 || tmp != ':')
                test_error("Unexpected netstat format (%c)", tmp);
index 92276f916f2f30d080ba3e1f5521c492192f8e98..e408b9243b2c5a5cf66785518fbfc16f2682b169 100644 (file)
@@ -17,37 +17,37 @@ static pthread_mutex_t ksft_print_lock = PTHREAD_MUTEX_INITIALIZER;
 void __test_msg(const char *buf)
 {
        pthread_mutex_lock(&ksft_print_lock);
-       ksft_print_msg(buf);
+       ksft_print_msg("%s", buf);
        pthread_mutex_unlock(&ksft_print_lock);
 }
 void __test_ok(const char *buf)
 {
        pthread_mutex_lock(&ksft_print_lock);
-       ksft_test_result_pass(buf);
+       ksft_test_result_pass("%s", buf);
        pthread_mutex_unlock(&ksft_print_lock);
 }
 void __test_fail(const char *buf)
 {
        pthread_mutex_lock(&ksft_print_lock);
-       ksft_test_result_fail(buf);
+       ksft_test_result_fail("%s", buf);
        pthread_mutex_unlock(&ksft_print_lock);
 }
 void __test_xfail(const char *buf)
 {
        pthread_mutex_lock(&ksft_print_lock);
-       ksft_test_result_xfail(buf);
+       ksft_test_result_xfail("%s", buf);
        pthread_mutex_unlock(&ksft_print_lock);
 }
 void __test_error(const char *buf)
 {
        pthread_mutex_lock(&ksft_print_lock);
-       ksft_test_result_error(buf);
+       ksft_test_result_error("%s", buf);
        pthread_mutex_unlock(&ksft_print_lock);
 }
 void __test_skip(const char *buf)
 {
        pthread_mutex_lock(&ksft_print_lock);
-       ksft_test_result_skip(buf);
+       ksft_test_result_skip("%s", buf);
        pthread_mutex_unlock(&ksft_print_lock);
 }
 
index 7df8b8700e39e96292f8eafdf105ee0314a65497..a2fe88d35ac06e4f534bd4d452670528d9f77219 100644 (file)
@@ -256,8 +256,6 @@ static int test_wait_fds(int sk[], size_t nr, bool is_writable[],
 
 static void test_client_active_rst(unsigned int port)
 {
-       /* one in queue, another accept()ed */
-       unsigned int wait_for = backlog + 2;
        int i, sk[3], err;
        bool is_writable[ARRAY_SIZE(sk)] = {false};
        unsigned int last = ARRAY_SIZE(sk) - 1;
@@ -275,16 +273,20 @@ static void test_client_active_rst(unsigned int port)
        for (i = 0; i < last; i++) {
                err = _test_connect_socket(sk[i], this_ip_dest, port,
                                               (i == 0) ? TEST_TIMEOUT_SEC : -1);
-
                if (err < 0)
                        test_error("failed to connect()");
        }
 
-       synchronize_threads(); /* 2: connection accept()ed, another queued */
-       err = test_wait_fds(sk, last, is_writable, wait_for, TEST_TIMEOUT_SEC);
+       synchronize_threads(); /* 2: two connections: one accept()ed, another queued */
+       err = test_wait_fds(sk, last, is_writable, last, TEST_TIMEOUT_SEC);
        if (err < 0)
                test_error("test_wait_fds(): %d", err);
 
+       /* async connect() with third sk to get into request_sock_queue */
+       err = _test_connect_socket(sk[last], this_ip_dest, port, -1);
+       if (err < 0)
+               test_error("failed to connect()");
+
        synchronize_threads(); /* 3: close listen socket */
        if (test_client_verify(sk[0], packet_sz, quota / packet_sz, TEST_TIMEOUT_SEC))
                test_fail("Failed to send data on connected socket");
@@ -292,13 +294,14 @@ static void test_client_active_rst(unsigned int port)
                test_ok("Verified established tcp connection");
 
        synchronize_threads(); /* 4: finishing up */
-       err = _test_connect_socket(sk[last], this_ip_dest, port, -1);
-       if (err < 0)
-               test_error("failed to connect()");
 
        synchronize_threads(); /* 5: closed active sk */
-       err = test_wait_fds(sk, ARRAY_SIZE(sk), NULL,
-                           wait_for, TEST_TIMEOUT_SEC);
+       /*
+        * Wait for 2 connections: one accepted, another in the accept queue,
+        * the one in request_sock_queue won't get fully established, so
+        * doesn't receive an active RST, see inet_csk_listen_stop().
+        */
+       err = test_wait_fds(sk, last, NULL, last, TEST_TIMEOUT_SEC);
        if (err < 0)
                test_error("select(): %d", err);
 
index 452de131fa3a9c720cd1fc4b9dc24438fd01d15d..517930f9721bd9b062d178def9fb296c17353119 100644 (file)
@@ -21,7 +21,7 @@ static void make_listen(int sk)
 static void test_vefify_ao_info(int sk, struct tcp_ao_info_opt *info,
                                const char *tst)
 {
-       struct tcp_ao_info_opt tmp;
+       struct tcp_ao_info_opt tmp = {};
        socklen_t len = sizeof(tmp);
 
        if (getsockopt(sk, IPPROTO_TCP, TCP_AO_INFO, &tmp, &len))
index 1d975bf52af33908593f61894233f9d8560cb16f..85b3baa3f7f34112ea95239c8819a2b1d834e22a 100644 (file)
@@ -34,7 +34,7 @@
 #endif
 
 #ifndef UDP_MAX_SEGMENTS
-#define UDP_MAX_SEGMENTS       (1 << 6UL)
+#define UDP_MAX_SEGMENTS       (1 << 7UL)
 #endif
 
 #define CONST_MTU_TEST 1500
index 505294da1b9fb5e7bd07aac4a119164900c8f2e6..d6f99eb9be659d3c9bb60b922e4f81102ac7f918 100644 (file)
@@ -154,7 +154,7 @@ static int dev_papr_vpd_null_handle(void)
 static int papr_vpd_close_handle_without_reading(void)
 {
        const int devfd = open(DEVPATH, O_RDONLY);
-       struct papr_location_code lc;
+       struct papr_location_code lc = { .str = "", };
        int fd;
 
        SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
index c537d52fafc586d5644ca6f7ec13a4358b4051c0..a40541bb7c7dee55baf1ec3e40c0727907a1c98d 100644 (file)
@@ -19,7 +19,7 @@
 #include "hwprobe.h"
 #include "../../kselftest.h"
 
-#define MK_CBO(fn) cpu_to_le32((fn) << 20 | 10 << 15 | 2 << 12 | 0 << 7 | 15)
+#define MK_CBO(fn) le32_bswap((uint32_t)(fn) << 20 | 10 << 15 | 2 << 12 | 0 << 7 | 15)
 
 static char mem[4096] __aligned(4096) = { [0 ... 4095] = 0xa5 };
 
index e3fccb390c4dc94d0c224223192f767606b4da17..f3de970c32227bcfc6c9ce8608ba497724326b1c 100644 (file)
@@ -4,6 +4,16 @@
 #include <stddef.h>
 #include <asm/hwprobe.h>
 
+#if __BYTE_ORDER == __BIG_ENDIAN
+# define le32_bswap(_x)                                \
+       ((((_x) & 0x000000ffU) << 24) |         \
+        (((_x) & 0x0000ff00U) <<  8) |         \
+        (((_x) & 0x00ff0000U) >>  8) |         \
+        (((_x) & 0xff000000U) >> 24))
+#else
+# define le32_bswap(_x) (_x)
+#endif
+
 /*
  * Rather than relying on having a new enough libc to define this, just do it
  * ourselves.  This way we don't need to be coupled to a new-enough libc to
index b5d592d4099e85c6ad9d19d36de055eb27415409..d975a67673299fe7fd617c4568e1c3afca93a96e 100644 (file)
@@ -158,6 +158,20 @@ static void handle_sigsys(int sig, siginfo_t *info, void *ucontext)
 
        /* In preparation for sigreturn. */
        SYSCALL_DISPATCH_OFF(glob_sel);
+
+       /*
+        * The tests for argument handling assume that `syscall(x) == x`. This
+        * is a NOP on x86 because the syscall number is passed in %rax, which
+        * happens to also be the function ABI return register.  Other
+        * architectures may need to swizzle the arguments around.
+        */
+#if defined(__riscv)
+/* REG_A7 is not defined in libc headers */
+# define REG_A7 (REG_A0 + 7)
+
+       ((ucontext_t *)ucontext)->uc_mcontext.__gregs[REG_A0] =
+                       ((ucontext_t *)ucontext)->uc_mcontext.__gregs[REG_A7];
+#endif
 }
 
 TEST(dispatch_and_return)
index fb49c2a602002ed30a5f426203fa0e30be2436b0..ff0a20565f9087e05e7e086f20025efd52c60819 100644 (file)
@@ -832,8 +832,7 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
         * mn_active_invalidate_count (see above) instead of
         * mmu_invalidate_in_progress.
         */
-       gfn_to_pfn_cache_invalidate_start(kvm, range->start, range->end,
-                                         hva_range.may_block);
+       gfn_to_pfn_cache_invalidate_start(kvm, range->start, range->end);
 
        /*
         * If one or more memslots were found and thus zapped, notify arch code
index ecefc7ec51af8516c14c13bf0ad68ad1bc369e77..715f19669d01f72912af9b7393ccd01f65c0527e 100644 (file)
@@ -26,13 +26,11 @@ kvm_pfn_t hva_to_pfn(unsigned long addr, bool atomic, bool interruptible,
 #ifdef CONFIG_HAVE_KVM_PFNCACHE
 void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm,
                                       unsigned long start,
-                                      unsigned long end,
-                                      bool may_block);
+                                      unsigned long end);
 #else
 static inline void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm,
                                                     unsigned long start,
-                                                    unsigned long end,
-                                                    bool may_block)
+                                                    unsigned long end)
 {
 }
 #endif /* HAVE_KVM_PFNCACHE */
index 4e07112a24c2f6d02f67ee22a7f7eaa15c5f098b..e3453e869e92c8f6546b7aa76ce8b3a2b486df4f 100644 (file)
@@ -23,7 +23,7 @@
  * MMU notifier 'invalidate_range_start' hook.
  */
 void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm, unsigned long start,
-                                      unsigned long end, bool may_block)
+                                      unsigned long end)
 {
        struct gfn_to_pfn_cache *gpc;
 
@@ -57,6 +57,19 @@ void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm, unsigned long start,
        spin_unlock(&kvm->gpc_lock);
 }
 
+static bool kvm_gpc_is_valid_len(gpa_t gpa, unsigned long uhva,
+                                unsigned long len)
+{
+       unsigned long offset = kvm_is_error_gpa(gpa) ? offset_in_page(uhva) :
+                                                      offset_in_page(gpa);
+
+       /*
+        * The cached access must fit within a single page. The 'len' argument
+        * to activate() and refresh() exists only to enforce that.
+        */
+       return offset + len <= PAGE_SIZE;
+}
+
 bool kvm_gpc_check(struct gfn_to_pfn_cache *gpc, unsigned long len)
 {
        struct kvm_memslots *slots = kvm_memslots(gpc->kvm);
@@ -74,7 +87,7 @@ bool kvm_gpc_check(struct gfn_to_pfn_cache *gpc, unsigned long len)
        if (kvm_is_error_hva(gpc->uhva))
                return false;
 
-       if (offset_in_page(gpc->uhva) + len > PAGE_SIZE)
+       if (!kvm_gpc_is_valid_len(gpc->gpa, gpc->uhva, len))
                return false;
 
        if (!gpc->valid)
@@ -232,8 +245,7 @@ out_error:
        return -EFAULT;
 }
 
-static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long uhva,
-                            unsigned long len)
+static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long uhva)
 {
        unsigned long page_offset;
        bool unmap_old = false;
@@ -247,15 +259,6 @@ static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned l
        if (WARN_ON_ONCE(kvm_is_error_gpa(gpa) == kvm_is_error_hva(uhva)))
                return -EINVAL;
 
-       /*
-        * The cached acces must fit within a single page. The 'len' argument
-        * exists only to enforce that.
-        */
-       page_offset = kvm_is_error_gpa(gpa) ? offset_in_page(uhva) :
-                                             offset_in_page(gpa);
-       if (page_offset + len > PAGE_SIZE)
-               return -EINVAL;
-
        lockdep_assert_held(&gpc->refresh_lock);
 
        write_lock_irq(&gpc->lock);
@@ -270,6 +273,8 @@ static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned l
        old_uhva = PAGE_ALIGN_DOWN(gpc->uhva);
 
        if (kvm_is_error_gpa(gpa)) {
+               page_offset = offset_in_page(uhva);
+
                gpc->gpa = INVALID_GPA;
                gpc->memslot = NULL;
                gpc->uhva = PAGE_ALIGN_DOWN(uhva);
@@ -279,6 +284,8 @@ static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned l
        } else {
                struct kvm_memslots *slots = kvm_memslots(gpc->kvm);
 
+               page_offset = offset_in_page(gpa);
+
                if (gpc->gpa != gpa || gpc->generation != slots->generation ||
                    kvm_is_error_hva(gpc->uhva)) {
                        gfn_t gfn = gpa_to_gfn(gpa);
@@ -354,6 +361,9 @@ int kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, unsigned long len)
 
        guard(mutex)(&gpc->refresh_lock);
 
+       if (!kvm_gpc_is_valid_len(gpc->gpa, gpc->uhva, len))
+               return -EINVAL;
+
        /*
         * If the GPA is valid then ignore the HVA, as a cache can be GPA-based
         * or HVA-based, not both.  For GPA-based caches, the HVA will be
@@ -361,7 +371,7 @@ int kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, unsigned long len)
         */
        uhva = kvm_is_error_gpa(gpc->gpa) ? gpc->uhva : KVM_HVA_ERR_BAD;
 
-       return __kvm_gpc_refresh(gpc, gpc->gpa, uhva, len);
+       return __kvm_gpc_refresh(gpc, gpc->gpa, uhva);
 }
 
 void kvm_gpc_init(struct gfn_to_pfn_cache *gpc, struct kvm *kvm)
@@ -381,6 +391,9 @@ static int __kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned
 {
        struct kvm *kvm = gpc->kvm;
 
+       if (!kvm_gpc_is_valid_len(gpa, uhva, len))
+               return -EINVAL;
+
        guard(mutex)(&gpc->refresh_lock);
 
        if (!gpc->active) {
@@ -400,11 +413,18 @@ static int __kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned
                gpc->active = true;
                write_unlock_irq(&gpc->lock);
        }
-       return __kvm_gpc_refresh(gpc, gpa, uhva, len);
+       return __kvm_gpc_refresh(gpc, gpa, uhva);
 }
 
 int kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long len)
 {
+       /*
+        * Explicitly disallow INVALID_GPA so that the magic value can be used
+        * by KVM to differentiate between GPA-based and HVA-based caches.
+        */
+       if (WARN_ON_ONCE(kvm_is_error_gpa(gpa)))
+               return -EINVAL;
+
        return __kvm_gpc_activate(gpc, gpa, KVM_HVA_ERR_BAD, len);
 }